- update SDK help content to wiki content in svn (help also gets updated before each build)

- fix remote help updating by using different server URL

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8435 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 13 years ago
parent d4c69da2a1
commit 38c9b14350
  1. 2
      sdk/jme3-core/build.xml
  2. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme2/terrain-from-float-array.png
  3. 133
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/3d_models.html
  4. 522
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/animation.html
  5. 323
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/application_states.html
  6. 247
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html
  7. 326
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/audio.html
  8. 212
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/audio_environment_presets.html
  9. 357
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html
  10. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/border1.png
  11. 43
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bullet_multithreading.html
  12. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png
  13. 305
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html
  14. 660
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/cinematics.html
  15. 331
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/collision_and_intersection.html
  16. 293
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/combo_moves.html
  17. 214
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html
  18. 315
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html
  19. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png
  20. 161
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/debugging.html
  21. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png
  22. 290
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html
  23. 114
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/endless_terraingrid.html
  24. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png
  25. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/gui-layout-draft.png
  26. 95
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/headless_server.html
  27. 278
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html
  28. 263
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/hud.html
  29. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/inner1.png
  30. 462
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/input_handling.html
  31. 498
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html
  32. 392
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/jme3_shaders.html
  33. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png
  34. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light-sources.png
  35. 252
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html
  36. 572
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/loading_screen.html
  37. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/loadingscreen.png
  38. 245
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/localization.html
  39. 131
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/logging.html
  40. 176
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/making_the_camera_follow_a_character.html
  41. 153
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html
  42. 425
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html
  43. 292
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mesh.html
  44. 324
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/monkey_zone.html
  45. 120
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/motionpath.html
  46. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mouse-picking.png
  47. 149
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/mouse_picking.html
  48. 164
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/multiple_camera_views.html
  49. 207
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/multithreading.html
  50. 593
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/networking.html
  51. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-13.png
  52. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-example.png
  53. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-panels.png
  54. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-simple-demo.png
  55. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png
  56. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty-screen-layer-panel.png
  57. 340
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html
  58. 429
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html
  59. 633
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html
  60. 127
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html
  61. 135
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html
  62. 494
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html
  63. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/open-game-finder-1.png
  64. 192
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/open_game_finder.html
  65. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otoglow.png
  66. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png
  67. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle.png
  68. 401
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html
  69. 811
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics.html
  70. 219
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/physics_listeners.html
  71. 431
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/post-processor_water.html
  72. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/pssm.png
  73. 230
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html
  74. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png
  75. 29
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/read_graphic_card_capabilites.html
  76. 53
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/remote-controlling_the_camera.html
  77. 48
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/save_and_load.html
  78. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shadow.png
  79. 180
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/shape.html
  80. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/simplewater.png
  81. 143
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/sky.html
  82. 197
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/spatial.html
  83. 200
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html
  84. 203
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/terrain.html
  85. 324
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/terrain_collision.html
  86. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png
  87. 126
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/update_loop.html
  88. 403
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/vehicles.html
  89. 411
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/walking_character.html
  90. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png
  91. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water-post.png
  92. 270
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.html
  93. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/water.png
  94. 250
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/android.html
  95. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/android_access.png
  96. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-assets-models.png
  97. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png
  98. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-materials.png
  99. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-physics.png
  100. BIN
      sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/beginner/beginner-scene.png
  101. Some files were not shown because too many files have changed in this diff Show More

@ -42,7 +42,7 @@
<!-- download images from page (custom task) -->
<loadwikiimages file="javahelp/${javahelp_path}${page_path}.html"
target="javahelp/${javahelp_path}"
host="http://jmonkeyengine.org"/>
host="http://direct.jmonkeyengine.org"/>
<!-- fix links in wiki (custom task) -->
<fixwikilinks file="javahelp/${javahelp_path}${page_path}.html"
helppath="${javahelp_path}"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 191 KiB

@ -1,49 +1,84 @@
<h1><a
name="models_and_scenes">Models and Scenes</a></h1><div
class="level1"><p> Like <a
href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s, 3D models are also made up of <a
href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a>es, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors.</p></div><h2><a
name="using_models_and_scenes_with_jme3">Using Models and Scenes with jME3</a></h2><div
class="level2"><p> To use 3D models in a jME3 application:</p><ol><li
class="level1"><div
class="li"> Export the 3D model in Ogre <acronym
title="Extensible Markup Language">XML</acronym> or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div></li><li
class="level1"><div
class="li"> Save the files into a subdirectory of your jME3 project&#039;s <code>assets</code> directory.</div></li><li
class="level1"><div
class="li"> In your code, you use the <a
href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models as <a
href="/com/jme3/gde/core/docs/jme3/advanced/spatial.html">Spatial</a>s into a jME application.<pre>Spatial model = assetManager.loadModel&#40;
&quot;Models/MonkeyHead/MonkeyHead.mesh.xml&quot; &#41;;</pre></div></li><li
class="level1"><div
class="li"> (For the release build:) Use the jMonkeyPlatform to convert models to .j3o format. You don&#039;t need this step as long you still develop and test the aplication within the jMonkeyPlatform.</div></li></ol></div><h2><a
name="creating_models_and_scenes">Creating Models and Scenes</a></h2><div
class="level2"><p> To create 3D models and scenes, you need a 3D Mesh Editor such as <a
href="http://www.blender.org/">Blender</a>, with an OgreXML Exporter plugin.</p><p> <strong>Tip:</strong> Consider creating <a
href="http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/UV_Map_Basics">UV textures</a> for more complex models, it looks more professional.</p><p> 3D mesh editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users:</p><p> To export your models as Ogre <acronym
title="Extensible Markup Language">XML</acronym> meshes with materials:</p><ol><li
class="level1"><div
class="li"> Open the menu File &gt; Export &gt; OgreXML Exporter to open the exporter dialog.</div></li><li
class="level1"><div
class="li"> In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some <acronym
title="Joint Photographics Experts Group">JPG</acronym> files.</div></li><li
class="level1"><div
class="li"> In the Export Meshes field: Select a target subdirectory of your <code>assets/Models/</code> directory. E.g. <code>assets/Models/something/</code>.</div></li><li
class="level1"><div
class="li"> Activate the following exporter settings:</div><ul><li
class="level2"><div
class="li"> Copy Textures: YES</div></li><li
class="level2"><div
class="li"> Rendering Materials: YES</div></li><li
class="level2"><div
class="li"> Flip Axis: YES</div></li><li
class="level2"><div
class="li"> Require Materials: YES</div></li><li
class="level2"><div
class="li"> Skeleton name follows mesh: YES</div></li></ul></li><li
class="level1"><div
class="li"> Click export.</div></li></ol><p> You can now use the <a
href="/com/jme3/gde/core/docs/sdk.html">jMonkeyPlatform</a> to <a
href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">load and view models</a>. You can <a
href="/com/jme3/gde/core/docs/sdk/scene_composer.html">create scenes</a> from them and write cde that loads them into your application.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:3d_models?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Models and Scenes</a></h1>
<div>
<p>
Like <a href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s, 3D models are also made up of <a href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a>es, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors.
</p>
</div>
<h2><a>Using Models and Scenes with jME3</a></h2>
<div>
<p>
To use 3D models in a jME3 application:
</p>
<ol>
<li><div> Export the 3D model in Ogre <acronym title="Extensible Markup Language">XML</acronym> or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div>
</li>
<li><div> Save the files into a subdirectory of your jME3 project&#039;s <code>assets</code> directory.</div>
</li>
<li><div> In your code, you use the <a href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models as <a href="/com/jme3/gde/core/docs/jme3/advanced/spatial.html">Spatial</a>s into a jME application. <pre>Spatial model = assetManager.loadModel&#40;
&quot;Models/MonkeyHead/MonkeyHead.mesh.xml&quot; &#41;;</pre>
</div>
</li>
<li><div> (For the release build:) Use the jMonkeyPlatform to convert models to .j3o format. You don&#039;t need this step as long you still develop and test the aplication within the jMonkeyPlatform.</div>
</li>
</ol>
</div>
<h2><a>Creating Models and Scenes</a></h2>
<div>
<p>
To create 3D models and scenes, you need a 3D Mesh Editor such as <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.blender.org/"><param name="text" value="<html><u>Blender</u></html>"><param name="textColor" value="blue"></object>, with an OgreXML Exporter plugin.
</p>
<p>
<strong>Tip:</strong> Consider creating <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/UV_Map_Basics"><param name="text" value="<html><u>UV textures</u></html>"><param name="textColor" value="blue"></object> for more complex models, it looks more professional.
</p>
<p>
3D mesh editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users:
</p>
<p>
To export your models as Ogre <acronym title="Extensible Markup Language">XML</acronym> meshes with materials:
</p>
<ol>
<li><div> Open the menu File &gt; Export &gt; OgreXML Exporter to open the exporter dialog.</div>
</li>
<li><div> In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some <acronym title="Joint Photographics Experts Group">JPG</acronym> files.</div>
</li>
<li><div> In the Export Meshes field: Select a target subdirectory of your <code>assets/Models/</code> directory. E.g. <code>assets/Models/something/</code>.</div>
</li>
<li><div> Activate the following exporter settings: </div>
<ul>
<li><div> Copy Textures: YES</div>
</li>
<li><div> Rendering Materials: YES</div>
</li>
<li><div> Flip Axis: YES</div>
</li>
<li><div> Require Materials: YES</div>
</li>
<li><div> Skeleton name follows mesh: YES</div>
</li>
</ul>
</li>
<li><div> Click export.</div>
</li>
</ol>
<p>
You can now use the <a href="/com/jme3/gde/core/docs/sdk.html">jMonkeyPlatform</a> to <a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">load and view models</a>. You can <a href="/com/jme3/gde/core/docs/sdk/scene_composer.html">create scenes</a> from them and write cde that loads them into your application.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:3d_models?do=export_xhtmlbody">view online version</a></em></p>

@ -1,157 +1,286 @@
<h1><a
name="animation_in_jme3">Animation in jME3</a></h1><div
class="level1"><p> In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code. Animated models must be created in an external mesh editor (for example, Blender).</p><p> What is required for the model?</p><ol><li
class="level1"><div
class="li"> For each model, you have to define a skeleton (bones rigging).</div></li><li
class="level1"><div
class="li"> For each motion, you have to specify how it distorts the model (skinning).</div></li><li
class="level1"><div
class="li"> For each animation, you have to specify a series of snapshots of how the bones are positioned (keyframes).</div></li><li
class="level1"><div
class="li"> One model can contain several animations. You give every animation a name when you save it in the mesh editor.</div></li></ol><p> More information: <a
href="/com/jme3/gde/core/docs/jme3/terminology#animation.html">Animation</a></p><p> What is required in your java class?</p><ul><li
class="level1"><div
class="li"> One animation controller per animated Model</div></li><li
class="level1"><div
class="li"> As many channels per controller as you need to play several animations in parallel. In simple cases one channel is enough, sometimes you need two or more per model.</div></li></ul></div><h2><a
name="controlling_animations">Controlling Animations</a></h2><div
class="level2"></div><h3><a
name="the_controller">The Controller</a></h3><div
class="level3"><p> Create one <code>com.jme3.animation.AnimControl</code> object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controllers. The control object gives you access to the available animation sequences in the model.</p><pre> AnimControl playerControl; // you need one controller per model
<h1><a>Animation in jME3</a></h1>
<div>
<p>
In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code. Animated models must be created in an external mesh editor (for example, Blender).
</p>
<p>
What is required for the model?
</p>
<ol>
<li><div> For each model, you have to define a skeleton (bones rigging). </div>
</li>
<li><div> For each motion, you have to specify how it distorts the model (skinning). </div>
</li>
<li><div> For each animation, you have to specify a series of snapshots of how the bones are positioned (keyframes).</div>
</li>
<li><div> One model can contain several animations. You give every animation a name when you save it in the mesh editor.</div>
</li>
</ol>
<p>
More information: <a href="/com/jme3/gde/core/docs/jme3/terminology#animation.html">Animation</a>
</p>
<p>
What is required in your java class?
</p>
<ul>
<li><div> One animation controller per animated Model</div>
</li>
<li><div> As many channels per controller as you need to play several animations in parallel. In simple cases one channel is enough, sometimes you need two or more per model.</div>
</li>
</ul>
</div>
<h2><a>Code Samples</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestSpatialAnim.java"><param name="text" value="<html><u>TestSpatialAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestBlenderAnim.java"><param name="text" value="<html><u>TestBlenderAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestBlenderObjectAnim.java"><param name="text" value="<html><u>TestBlenderObjectAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestOgreAnim.java"><param name="text" value="<html><u>TestOgreAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestOgreComplexAnim.java"><param name="text" value="<html><u>TestOgreComplexAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/model/anim/TestCustomAnim.java"><param name="text" value="<html><u>TestCustomAnim.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Controlling Animations</a></h2>
<div>
</div>
<h3><a>The Controller</a></h3>
<div>
<p>
Create one <code>com.jme3.animation.AnimControl</code> object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controllers. The control object gives you access to the available animation sequences in the model.
</p>
<pre> AnimControl playerControl; // you need one controller per model
Node player = &#40;Node&#41; assetManager.loadModel&#40;&quot;Models/Oto/Oto.mesh.xml&quot;&#41;; // load a model
playerControl = player.getControl&#40;AnimControl.class&#41;; // get control over this model
playerControl.addListener&#40;this&#41;; // add listener</pre></div><h3><a
name="channels">Channels</a></h3><div
class="level3"><p> A controller has several animation channels (<code>com.jme3.animation.AnimChannel</code>). Each channel can play one animation sequence at a time.</p><p> There often are situations where you want to run several animation sequences at the same time, e.g. &quot;shooting while walking&quot; or &quot;boxing while jumping&quot;. In this case, you create several channels, assign an animation to each, and play them in parallel.</p><pre> AnimChannel channel_walk = playerControl.createChannel&#40;&#41;;
playerControl.addListener&#40;this&#41;; // add listener</pre>
</div>
<h3><a>Channels</a></h3>
<div>
<p>
A controller has several animation channels (<code>com.jme3.animation.AnimChannel</code>). Each channel can play one animation sequence at a time.
</p>
<p>
There often are situations where you want to run several animation sequences at the same time, e.g. &quot;shooting while walking&quot; or &quot;boxing while jumping&quot;. In this case, you create several channels, assign an animation to each, and play them in parallel.
</p>
<pre> AnimChannel channel_walk = playerControl.createChannel&#40;&#41;;
AnimChannel channel_jump = playerControl.createChannel&#40;&#41;;
...</pre><p> To reset a controller, call <code>control.clearChannels();</code></p></div><h2><a
name="animation_control_properties">Animation Control Properties</a></h2><div
class="level2"><p> The following information is available for an AnimControl.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">AnimControl Property</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">createChannel()</td><td
class="col1">Returns a new channel, controlling all bones by default.</td></tr><tr
class="row2"><td
class="col0">getNumChannels()</td><td
class="col1">The number of channels registered to this Control.</td></tr><tr
class="row3"><td
class="col0">getChannel(0)</td><td
class="col1">Gets individual channels by index number. At most <code>getNumChannels()</code>.</td></tr><tr
class="row4"><td
class="col0">clearChannels()</td><td
class="col1">Clear all channels in this control.</td></tr><tr
class="row5"><td
class="col0">addListener(animEventListener) <br/> removeListener(animEventListener) <br/> clearListeners()</td><td
class="col1">Adds or removes listeners to receive animation related events.</td></tr></table></div><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">AnimControl Property</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">setAnimations(aniHashMap)</td><td
class="col1">Sets the animations that this AnimControl is capable of playing. The animations must be compatible with the skeleton given in the constructor.</td></tr><tr
class="row2"><td
class="col0">addAnim(boneAnim) <br/> removeAnim(boneAnim)</td><td
class="col1">Adds or removes an animation from this Control.</td></tr><tr
class="row3"><td
class="col0">getAnimationNames()</td><td
class="col1">A String Collection of names of all animations that this Control can play for this model.</td></tr><tr
class="row4"><td
class="col0">getAnim(&quot;anim&quot;)</td><td
class="col1">Retrieve an animation from the list of animations.</td></tr><tr
class="row5"><td
class="col0">getAnimationLength(&quot;anim&quot;)</td><td
class="col1">Returns the length of the given named animation in seconds</td></tr></table></div><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0">AnimControl Property</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">getSkeleton()</td><td
class="col1">The Skeleton object controlled by this Control.</td></tr><tr
class="row2"><td
class="col0">getTargets()</td><td
class="col1">The Skin objects controlled by this Control, as Mesh array.</td></tr><tr
class="row3"><td
class="col0">getAttachmentsNode(&quot;bone&quot;)</td><td
class="col1">Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone&#039;s motions.</td></tr></table></div></div><h2><a
name="animation_channel_properties">Animation Channel Properties</a></h2><div
class="level2"><p> The following properties are set per AnimChannel.</p><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0">AnimChannel Property</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">setLoopMode(LoopMode.Loop);</td><td
class="col1"> From now on, the animation on this channel will repeat from the beginning when it ends.</td></tr><tr
class="row2"><td
class="col0">setLoopMode(LoopMode.DontLoop);</td><td
class="col1"> From now on, the animation on this channel will play once, and the freeze at the last keyframe.</td></tr><tr
class="row3"><td
class="col0">setLoopMode(LoopMode.Cycle);</td><td
class="col1"> From now on, the animation on this channel will play forward, then backward, then again forward, and so on.</td></tr><tr
class="row4"><td
class="col0">setSpeed(1f);</td><td
class="col1"> From now on, play this animation slower (&lt;1f) or faster (&gt;1f), or with default speed (1f).</td></tr><tr
class="row5"><td
class="col0">setTime(1.3f);</td><td
class="col1"> Fast-forward or rewind to a certain moment in time of this animation.</td></tr></table></div><p> The following information is available for a channel.</p><div
class="table sectionedit5"><table
class="inline"><tr
class="row0"><th
class="col0">AnimChannel Property</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">getAnimationName()</td><td
class="col1">The name of the animation playing on this channel. Returns <code>null</code> when no animation is playing.</td></tr><tr
class="row2"><td
class="col0">getLoopMode()</td><td
class="col1">The current loop mode on this channel. The returned com.jme3.animation enum can be LoopMode.Loop, LoopMode.DontLoop, or LoopMode.Cycle.</td></tr><tr
class="row3"><td
class="col0">getAnimMaxTime()</td><td
class="col1">The total length of the animation on this channel. Or <code>0f</code> if nothing is playing.</td></tr><tr
class="row4"><td
class="col0">getTime()</td><td
class="col1">How long the animation on this channel has been playing. It returns <code>0f</code> if the channel has not started playing yet, or a value up to getAnimMaxTime().</td></tr><tr
class="row5"><td
class="col0">getControl()</td><td
class="col1">The AnimControl that belongs to this AnimChannel.</td></tr></table></div><p> Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs).</p><div
class="table sectionedit6"><table
class="inline"><tr
class="row0"><th
class="col0">AnimChannel Methods</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">addAllBones()</td><td
class="col1">Add all the bones of the model&#039;s skeleton to be influenced by this animation channel. (default)</td></tr><tr
class="row2"><td
class="col0">addBone(&quot;bone1&quot;) <br/> addBone(bone1)</td><td
class="col1">Add a single bone to be influenced by this animation channel.</td></tr><tr
class="row3"><td
class="col0">addToRootBone(&quot;bone1&quot;) <br/> addToRootBone(bone1)</td><td
class="col1">Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given bone, to the root bone.</td></tr><tr
class="row4"><td
class="col0">addFromRootBone(&quot;bone1&quot;) <br/> addFromRootBone(bone1)</td><td
class="col1">Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.</td></tr></table></div></div><h2><a
name="playing_animations">Playing Animations</a></h2><div
class="level2"><p> Animations are played by channel. <strong>Note:</strong> Whether the animation channel plays continuously or only once, depends on the Loop properties you have set.</p><div
class="table sectionedit7"><table
class="inline"><tr
class="row0"><th
class="col0">Channel Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">channel_walk.setAnim(&quot;Walk&quot;,0.50f);</td><td
class="col1"> Start the animation named &quot;Walk&quot; on channel channel_walk. <br/> The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.</td></tr></table></div><p> <strong>Tip:</strong> Use the AnimEventLister below to react at the end or start of an animation cycle.</p></div><h3><a
name="usage_example">Usage Example</a></h3><div
class="level3"><p> In this short example, we define the space key to trigger playing the &quot;Walk&quot; animation on channel2.</p><pre> public void simpleInitApp&#40;&#41; &#123;
...</pre>
<p>
To reset a controller, call <code>control.clearChannels();</code>
</p>
</div>
<h2><a>Animation Control Properties</a></h2>
<div>
<p>
The following information is available for an AnimControl.
</p>
<div><table>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
<tr>
<td>createChannel()</td><td>Returns a new channel, controlling all bones by default.</td>
</tr>
<tr>
<td>getNumChannels()</td><td>The number of channels registered to this Control.</td>
</tr>
<tr>
<td>getChannel(0)</td><td>Gets individual channels by index number. At most <code>getNumChannels()</code>.</td>
</tr>
<tr>
<td>clearChannels()</td><td>Clear all channels in this control.</td>
</tr>
<tr>
<td>addListener(animEventListener) <br/>
removeListener(animEventListener) <br/>
clearListeners() </td><td>Adds or removes listeners to receive animation related events.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3269-3738] --><div><table>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
<tr>
<td>setAnimations(aniHashMap)</td><td>Sets the animations that this AnimControl is capable of playing. The animations must be compatible with the skeleton given in the constructor.</td>
</tr>
<tr>
<td>addAnim(boneAnim) <br/>
removeAnim(boneAnim)</td><td>Adds or removes an animation from this Control.</td>
</tr>
<tr>
<td>getAnimationNames()</td><td>A String Collection of names of all animations that this Control can play for this model.</td>
</tr>
<tr>
<td>getAnim(&quot;anim&quot;)</td><td>Retrieve an animation from the list of animations.</td>
</tr>
<tr>
<td>getAnimationLength(&quot;anim&quot;)</td><td>Returns the length of the given named animation in seconds</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [3740-4300] --><div><table>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
<tr>
<td>getSkeleton()</td><td>The Skeleton object controlled by this Control.</td>
</tr>
<tr>
<td>getTargets()</td><td>The Skin objects controlled by this Control, as Mesh array.</td>
</tr>
<tr>
<td>getAttachmentsNode(&quot;bone&quot;)</td><td>Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone&#039;s motions.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [4302-4617] -->
</div>
<h2><a>Animation Channel Properties</a></h2>
<div>
<p>
The following properties are set per AnimChannel.
</p>
<div><table>
<tr>
<th>AnimChannel Property</th><th>Usage</th>
</tr>
<tr>
<td>setLoopMode(LoopMode.Loop); </td><td> From now on, the animation on this channel will repeat from the beginning when it ends. </td>
</tr>
<tr>
<td>setLoopMode(LoopMode.DontLoop); </td><td> From now on, the animation on this channel will play once, and the freeze at the last keyframe. </td>
</tr>
<tr>
<td>setLoopMode(LoopMode.Cycle); </td><td> From now on, the animation on this channel will play forward, then backward, then again forward, and so on. </td>
</tr>
<tr>
<td>setSpeed(1f); </td><td> From now on, play this animation slower (&lt;1f) or faster (&gt;1f), or with default speed (1f). </td>
</tr>
<tr>
<td>setTime(1.3f); </td><td> Fast-forward or rewind to a certain moment in time of this animation. </td>
</tr>
</table></div>
<!-- EDIT4 TABLE [4713-5337] -->
<p>
The following information is available for a channel.
</p>
<div><table>
<tr>
<th>AnimChannel Property</th><th>Usage</th>
</tr>
<tr>
<td>getAnimationName()</td><td>The name of the animation playing on this channel. Returns <code>null</code> when no animation is playing.</td>
</tr>
<tr>
<td>getLoopMode()</td><td>The current loop mode on this channel. The returned com.jme3.animation enum can be LoopMode.Loop, LoopMode.DontLoop, or LoopMode.Cycle.</td>
</tr>
<tr>
<td>getAnimMaxTime()</td><td>The total length of the animation on this channel. Or <code>0f</code> if nothing is playing.</td>
</tr>
<tr>
<td>getTime()</td><td>How long the animation on this channel has been playing. It returns <code>0f</code> if the channel has not started playing yet, or a value up to getAnimMaxTime().</td>
</tr>
<tr>
<td>getControl()</td><td>The AnimControl that belongs to this AnimChannel.</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [5394-6027] -->
<p>
Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs).
</p>
<div><table>
<tr>
<th>AnimChannel Methods</th><th>Usage</th>
</tr>
<tr>
<td>addAllBones()</td><td>Add all the bones of the model&#039;s skeleton to be influenced by this animation channel. (default)</td>
</tr>
<tr>
<td>addBone(&quot;bone1&quot;) <br/>
addBone(bone1)</td><td>Add a single bone to be influenced by this animation channel.</td>
</tr>
<tr>
<td>addToRootBone(&quot;bone1&quot;) <br/>
addToRootBone(bone1) </td><td>Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given bone, to the root bone.</td>
</tr>
<tr>
<td>addFromRootBone(&quot;bone1&quot;) <br/>
addFromRootBone(bone1) </td><td>Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [6267-6888] -->
</div>
<h2><a>Playing Animations</a></h2>
<div>
<p>
Animations are played by channel. <strong>Note:</strong> Whether the animation channel plays continuously or only once, depends on the Loop properties you have set.
</p>
<div><table>
<tr>
<th>Channel Method</th><th>Usage</th>
</tr>
<tr>
<td>channel_walk.setAnim(&quot;Walk&quot;,0.50f); </td><td> Start the animation named &quot;Walk&quot; on channel channel_walk. <br/>
The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.</td>
</tr>
</table></div>
<!-- EDIT7 TABLE [7076-7402] -->
<p>
<strong>Tip:</strong> Use the AnimEventLister below to react at the end or start of an animation cycle.
</p>
</div>
<h3><a>Usage Example</a></h3>
<div>
<p>
In this short example, we define the space key to trigger playing the &quot;Walk&quot; animation on channel2.
</p>
<pre> public void simpleInitApp&#40;&#41; &#123;
...
inputManager.addMapping&#40;&quot;Walk&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;
inputManager.addListener&#40;actionListener, &quot;Walk&quot;&#41;;
@ -167,36 +296,81 @@ class="level3"><p> In this short example, we define the space key to trigger pla
&#125;
&#125;
&#125;
&#125;;</pre></div><h2><a
name="animation_event_listener">Animation Event Listener</a></h2><div
class="level2"><p> A jME3 application that contains animations can implement the <code>com.jme3.animation.AnimEventListener</code> interface.</p><pre>public class HelloAnimation extends SimpleApplication
implements AnimEventListener &#123; ... &#125;</pre><p> This optional Listener enables you to respond to animation start and end events, onAnimChange() and onAnimCycleDone().</p></div><h3><a
name="responding_to_animation_end">Responding to Animation End</a></h3><div
class="level3"><p> The onAnimCycleDone() event is invoked when an animation cycle has ended. For non-looping animations, this event is invoked when the animation is finished playing. For looping animations, this even is invoked each time the animation loop is restarted.</p><p> You have access to the following objects:</p><ul><li
class="level1"><div
class="li"> The controller to which the listener is assigned.</div></li><li
class="level1"><div
class="li"> The animation channel being played.</div></li><li
class="level1"><div
class="li"> The name of the animation that has just finished playing.</div></li></ul><pre> public void onAnimCycleDone&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123;
&#125;;</pre>
</div>
<h2><a>Animation Event Listener</a></h2>
<div>
<p>
A jME3 application that contains animations can implement the <code>com.jme3.animation.AnimEventListener</code> interface.
</p>
<pre>public class HelloAnimation extends SimpleApplication
implements AnimEventListener &#123; ... &#125;</pre>
<p>
This optional Listener enables you to respond to animation start and end events, onAnimChange() and onAnimCycleDone().
</p>
</div>
<h3><a>Responding to Animation End</a></h3>
<div>
<p>
The onAnimCycleDone() event is invoked when an animation cycle has ended. For non-looping animations, this event is invoked when the animation is finished playing. For looping animations, this even is invoked each time the animation loop is restarted.
</p>
<p>
You have access to the following objects:
</p>
<ul>
<li><div> The controller to which the listener is assigned.</div>
</li>
<li><div> The animation channel being played.</div>
</li>
<li><div> The name of the animation that has just finished playing.</div>
</li>
</ul>
<pre> public void onAnimCycleDone&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123;
// test for a condition you are interested in, e.g. ...
if &#40;animName.equals&#40;&quot;Walk&quot;&#41;&#41; &#123;
// respond to the event here, e.g. ...
channel.setAnim&#40;&quot;Stand&quot;, 0.50f&#41;;
&#125;
&#125;</pre></div><h3><a
name="responding_to_animation_start">Responding to Animation Start</a></h3><div
class="level3"><p> The onAnimChange() event is invoked every time before an animation is set by the user to be played on a given channel (<code>channel.setAnim()</code>).</p><p> You have access to the following objects</p><ul><li
class="level1"><div
class="li"> The controller to which the listener is assigned.</div></li><li
class="level1"><div
class="li"> The animation channel being played.</div></li><li
class="level1"><div
class="li"> The name of the animation that will start playing.</div></li></ul><pre> public void onAnimChange&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123;
&#125;</pre>
</div>
<h3><a>Responding to Animation Start</a></h3>
<div>
<p>
The onAnimChange() event is invoked every time before an animation is set by the user to be played on a given channel (<code>channel.setAnim()</code>).
</p>
<p>
You have access to the following objects
</p>
<ul>
<li><div> The controller to which the listener is assigned.</div>
</li>
<li><div> The animation channel being played.</div>
</li>
<li><div> The name of the animation that will start playing.</div>
</li>
</ul>
<pre> public void onAnimChange&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123;
// test for a condition you are interested in, e.g. ...
if &#40;animName.equals&#40;&quot;Walk&quot;&#41;&#41; &#123;
// respond to the event here, e.g. ...
channel.setAnim&#40;&quot;Reset&quot;, 0.50f&#41;;
&#125;
&#125;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:animation?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:animation?do=export_xhtmlbody">view online version</a></em></p>

@ -1,107 +1,238 @@
<h1><a
name="application_states">Application States</a></h1><div
class="level1"><p> <code>com.jme3.app.state.AppState</code> is a customizable jME3 interface that allows you to control the global game logic (game mechanics). To control the behaviour of a type of Spatial, see <a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> instead – both can be used together.</p><p> To implement game logic:</p><ol><li
class="level1"><div
class="li"> You define a custom AppState and implement its behaviour in the AppState&#039;s update() method.</div><ul><li
class="level2"><div
class="li"> You can pass arguments and manipulate everything inside the app&#039;s scope.</div></li></ul></li><li
class="level1"><div
class="li"> Attach the AppState to your application&#039;s AppStateManager (<code>stateManager.attach(myAppState);</code>) to activate it.</div></li><li
class="level1"><div
class="li"> Create one AppState for each type of game behavior. When you add several AppStates to one Application, they will be executed in the order they were added.</div></li></ol></div><h2><a
name="usage_examples">Usage Examples</a></h2><div
class="level2"><p> JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/jbullet/com/jme3/bullet/">BulletAppState</a> controls physical behaviour in PhysicsControl&#039;ed Spatials.</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/app/state/TestAppStates.java">TestAppStates.java</a> an example of a custom AppState</div><ul><li
class="level2"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/app/state/RootNodeState.java">RootNodeState.java</a></div></li></ul></li></ul></div><h2><a
name="appstate">AppState</a></h2><div
class="level2"><p> The AppState interface allows you to hook a continously executing piece of code into the main loop.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">AppState Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">isActive()</td><td
class="col1">Test whether AppState is enabled or disabled.</td></tr><tr
class="row2"><td
class="col0">stateAttached(asm) <br/> stateDetached(asm)</td><td
class="col1">The AppState knows when it is attached to, or detached from, the AppStateManager. Then it triggers these methods that you implement.</td></tr><tr
class="row3"><td
class="col0">isInitialized()</td><td
class="col1">Your implementations of this interface should return the correct respective boolean value.</td></tr><tr
class="row4"><td
class="col0">initialize(asm,app)</td><td
class="col1">The RenderThread initialized the AppState and then calls this method.</td></tr><tr
class="row5"><td
class="col0">setActive(true) <br/> setActive(false)</td><td
class="col1">Temporarily enables or disables an AppState.</td></tr><tr
class="row6"><td
class="col0">update(float tpf)</td><td
class="col1">Here you implement the behaviour that you want to hook into the main update loop.</td></tr><tr
class="row7"><td
class="col0">cleanup()</td><td
class="col1">Called when when the AppState is de-initialized.</td></tr><tr
class="row8"><td
class="col0">render(RenderManager rm)</td><td
class="col1">Renders the state.</td></tr><tr
class="row9"><td
class="col0">postRender()</td><td
class="col1">Called after all rendering commands are flushed.</td></tr></table></div></div><h2><a
name="abstractappstate">AbstractAppState</a></h2><div
class="level2"><p> The AbstractAppState class already implements some common methods and makes creation of custom AppStates a bit easier: isInitialized(), setActive(), isActive(), cleanUp(). Just extend it and override the remaining AppState methods.</p><p> Definition:</p><pre>public class MyAppState extends AbstractAppState &#123;
<h1><a>Application States</a></h1>
<div>
<p>
<code>com.jme3.app.state.AppState</code> is a customizable jME3 interface that allows you to control the global game logic (game mechanics). To control the behaviour of a type of Spatial, see <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> instead – both can be used together.
</p>
</div>
<h2><a>Use Case</a></h2>
<div>
<p>
There will be situations during your game development where you think:
</p>
<ul>
<li><div> Can I group a set of input handler settings, and activate and deactivate them all in one step? (e.g. mouse and key inputs are handled different in-game versus in the main menu.) </div>
</li>
<li><div> Can I group a bunch of nodes and swap them in and out in one step? (e.g. the in-game scene, versus a character editor, versus a Captain&#039;s Quarters screen)</div>
</li>
<li><div> Can I define what happens while the game is paused/unpaused, and toggle that in one step? </div>
</li>
<li><div> Can I wrap up one set of game mechanics and switch it on and off in one step? (e.g. a conditional block that takes up a lot of space in my update loop)</div>
</li>
<li><div> Can I package all of the above that belongs <em>in-game</em>, and also everthing that belongs to the main menu, and switch between these two &quot;big&quot; states in one step? </div>
</li>
</ul>
<p>
Yes you can! This is what AppStates are there for. A game state can be a subset of class fields (game data), <acronym title="Graphical User Interface">GUI</acronym> elements and their interactions, a subset of input handlers, a subset of nodes in the simpleInitApp() method, a subset of actions that you branch to in the simpleUpdate() loop, a set of AppStates and Controls – or combinations thereof.
</p>
<p>
Each AppState is such a grouped subset of such game states. Each AppState has hooks that let you define what happens to this set in the following situations:
</p>
<ul>
<li><div> the AppState is initialized: You load and initialize game data, InputHandlers, AppStates and Controls and attach nodes.</div>
</li>
<li><div> the AppState is cleaned up: You save the game state, unregister Controls, AppStates and InputHandlers, and detach nodes.</div>
</li>
<li><div> the AppState is temporarly disabled/enabled (paused/unpaused): You toggle a boolean to skip certain actions of the update loop, you display a paused screen <acronym title="Graphical User Interface">GUI</acronym>, and change the input handlers. </div>
</li>
</ul>
<p>
<strong>Tip:</strong> You can create AppStates that enable and disable sets of other AppStates, e.g. InGameState versus MainScreenState.
</p>
</div>
<h2><a>Usage</a></h2>
<div>
<p>
To implement game logic:
</p>
<ol>
<li><div> You define a custom AppState and implement its behaviour in the AppState&#039;s update() method.</div>
<ul>
<li><div> You can pass custom data as arguments in the constructor.</div>
</li>
<li><div> The AppState has access to everything inside the app&#039;s scope via the Application <code>app</code> object.</div>
</li>
</ul>
</li>
<li><div> Attach all AppStates to your application&#039;s AppStateManager (<code>stateManager.attach(myAppState);</code>), and activate and deactivate the ones you need.</div>
</li>
<li><div> Create one AppState for each set of game mechanics. </div>
</li>
</ol>
<p>
When you add several AppStates to one Application and activate them, their init methods and update loops are executed in the order in which the AppStates were added.
</p>
</div>
<h2><a>Examples</a></h2>
<div>
<p>
JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/jbullet/com/jme3/bullet/"><param name="text" value="<html><u>BulletAppState</u></html>"><param name="textColor" value="blue"></object> controls physical behaviour in PhysicsControl&#039;ed Spatials.</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/app/state/TestAppStates.java"><param name="text" value="<html><u>TestAppStates.java</u></html>"><param name="textColor" value="blue"></object> an example of a custom AppState</div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/app/state/RootNodeState.java"><param name="text" value="<html><u>RootNodeState.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
</ul>
</div>
<h2><a>AppState</a></h2>
<div>
<p>
The AppState interface allows you to initialize sets of objects, and hook a sets of continously executing code into the main loop.
</p>
<div><table>
<tr>
<th>AppState Method</th><th>Usage</th>
</tr>
<tr>
<td>stateAttached(asm) <br/>
stateDetached(asm)</td><td>The AppState knows when it is attached to, or detached from, the AppStateManager, and triggers these two methods. Here you implement what happens then.</td>
</tr>
<tr>
<td>initialize(asm,app)</td><td>The RenderThread initialized the AppState and then calls this method. Here you implement initSimpleApp()-style initialization code. </td>
</tr>
<tr>
<td>isInitialized()</td><td>Your implementations of this interface should return the correct respective boolean value.</td>
</tr>
<tr>
<td>setActive(true) <br/>
setActive(false)</td><td>Temporarily enables or disables an AppState. </td>
</tr>
<tr>
<td>isActive()</td><td>Test whether AppState is enabled or disabled. Your implementation should consider the boolean.</td>
</tr>
<tr>
<td>update(float tpf)</td><td>Here you implement the behaviour that you want to hook into the simpleUpdate() loop.</td>
</tr>
<tr>
<td>cleanup()</td><td>Called when when the AppState is de-initialized. Here you implement what clean-up code for this state.</td>
</tr>
<tr>
<td>render(RenderManager rm)</td><td>Renders the state, plus your optional customizations.</td>
</tr>
<tr>
<td>postRender()</td><td>Called after all rendering commands are flushed, including your optional customizations.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3823-4902] -->
</div>
<h2><a>AbstractAppState</a></h2>
<div>
<p>
The AbstractAppState class already implements some common methods and makes creation of custom AppStates a bit easier: isInitialized(), setActive(), isActive(), cleanUp(). Just extend it and override the remaining AppState methods.
Definition:
</p>
<pre>public class MyAppState extends AbstractAppState &#123;
private Node x = new Node&#40;&quot;x&quot;&#41;; // some class field
private SimpleApplication app;
&nbsp;
public Node getX&#40;&#41;&#123;
return x;
return x; // implement custom methods for this field
&#125;
&nbsp;
@Override
public void update&#40;float tpf&#41; &#123;
x.doSomething&#40;&#41;; // implement behaviour
&#125;
&#125;</pre><p> Usage:</p><pre>public class TestAppStates extends Application &#123;
public static void main&#40;String&#91;&#93; args&#41;&#123;
TestAppStates app = new TestAppStates&#40;&#41;;
app.start&#40;&#41;;
&#125;
&nbsp;
@Override
public void initialize&#40;&#41;&#123;
super.initialize&#40;&#41;;
MyAppState state = new MyAppState&#40;&#41;;
stateManager.attach&#40;state&#41;;
System.out.println&#40;&quot;Use the state's methods... &quot; + state.getX&#40;&#41;&#41;;
x.doSomething&#40;&#41;; // call some methods here
&#125;
&nbsp;
@Override
public void update&#40;&#41;&#123;
super.update&#40;&#41;;
stateManager.update&#40;tpf&#41;;
stateManager.render&#40;renderManager&#41;;
renderManager.render&#40;tpf&#41;;
public void initialize&#40;AppStateManager stateManager, Application app&#41; &#123;
super.initialize&#40;stateManager, app&#41;;
this.app=&#40;SimpleApplication&#41;app;
app.doSomething&#40;&#41;; // call some methods elsewhere
&#125;
&#125;</pre><p> <strong>Note:</strong> If you use the AppState together with a SimpleApplication-based class, then this <code>update()</code> loop is already set up.</p></div><h2><a
name="appstatemanager">AppStateManager</a></h2><div
class="level2"><p> The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates are updated and rendered. When an AppState is attached, AppStateManager calls its stateAttached() method. When an AppState is detached, AppStateManager calls its stateDetached() method.</p><p> There is one AppStateManager per application. You can attach several AppStates to one AppStateManager, but the same state can only be attached once.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">AppStateManager Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">hasState(s)</td><td
class="col1">Is AppState s attached?</td></tr><tr
class="row2"><td
class="col0">getState(Class&lt;T&gt; stateClass)</td><td
class="col1">Returns the first state that is an instance of a subclass of the specified class.</td></tr></table></div><p> The AppStateManager&#039;s update(), render(), postRender(), and cleanUp() methods are internal, users never call them directly.</p></div><h2><a
name="best_practices">Best Practices</a></h2><div
class="level2"><p> You can only change AppStates, or read and write to them, from certain places: In a Control&#039;s update() method, in an AppState&#039;s update() method, and it the SimpleApplication&#039;s simpleUpdate() loop (or the Application&#039;s update() loop).</p><p> To get data from the AppState <code>MyAppState</code>:</p><pre>app.getState&#40;MyAppState.class&#41;.getInfoAboutSomething&#40;&#41;;</pre><p> To pass new data into the AppState <code>MyAppState</code>:</p><pre>app.getState&#40;MyAppState.class&#41;.setSomething&#40;blah&#41;;</pre><p> To trigger a one-off method in the AppState <code>MyAppState</code>:</p><pre>app.getState&#40;MyAppState.class&#41;.doSomeMoreStuff&#40;&#41;;</pre><p> Don&#039;t mess with the AppState from other places, because from other methods you have no control over the order of updates. You don&#039;t know when (during which half-finished step of an update), your call was received.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:application_states?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
</div>
<h2><a>AppStateManager</a></h2>
<div>
<p>
The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates are updated and rendered. When an AppState is attached, AppStateManager calls its stateAttached() method. When an AppState is detached, AppStateManager calls its stateDetached() method.
There is one AppStateManager per application. You can attach several AppStates to one AppStateManager, but the same state can only be attached once.
</p>
<div><table>
<tr>
<th>AppStateManager Method</th><th>Usage</th>
</tr>
<tr>
<td>hasState(s)</td><td>Is AppState s attached?</td>
</tr>
<tr>
<td>getState(Class&lt;T&gt; stateClass)</td><td>Returns the first state that is an instance of a subclass of the specified class.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [6328-6510] -->
<p>
The AppStateManager&#039;s update(), render(), postRender(), and cleanUp() methods are internal, users never call them directly.
</p>
</div>
<h2><a>Best Practices</a></h2>
<div>
<p>
You can only change AppStates, or read and write to them, from certain places: In a Control&#039;s update() method, in an AppState&#039;s update() method, and in the SimpleApplication&#039;s simpleUpdate() loop (or the Application&#039;s update() loop).
To get data from the AppState <code>MyAppState</code>:
</p>
<pre>app.getState&#40;MyAppState.class&#41;.getInfoAboutSomething&#40;&#41;;</pre>
<p>
To pass new data into the AppState <code>MyAppState</code>:
</p>
<pre>app.getState&#40;MyAppState.class&#41;.setSomething&#40;blah&#41;;</pre>
<p>
To trigger a one-off method in the AppState <code>MyAppState</code>:
</p>
<pre>app.getState&#40;MyAppState.class&#41;.doSomeMoreStuff&#40;&#41;;</pre>
<p>
Don&#039;t mess with the AppState from other places, because from other methods you have no control over the order of updates. You don&#039;t know when (during which half-finished step of an update), your call was received.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:application_states?do=export_xhtmlbody">view online version</a></em></p>

@ -1,7 +1,48 @@
<h1><a
name="assetmanager">AssetManager</a></h1><div
class="level1"><p> JME3 has an integrated an asset manager that helps you keep your project assets organized. By assets we mean media files, such as 3D models, materials, textures, scenes, shaders, sounds, and fonts. Think of the asset manager as the filesystem of your game, independent of the actual deployment platform. It also manages the appropriate managing of OpenGL objects like textures so that they are e.g. not uploaded to the graphics card multiple times when multiple models use them.</p><p> The <code>assetManager</code> object is an com.jme3.asset.AssetManager instance that every com.jme3.app.Application can access. It maintains a root that also includes your project&#039;s classpath by default, so you can load any asset that&#039;s on the classpath, that is, the top level of your project directory.</p><p> You can use the inherited <code>assetManager</code> object directly, or use the accessor <code>getAssetManager()</code>.</p><p> Here is an example how you load assets using the AssetManager. This lines loads a default Material from the Common directory:</p><pre>Material mat = &#40;Material&#41; assetManager.loadAsset&#40;
new AssetKey&#40;&quot;Common/Materials/RedColor.j3m&quot;&#41;&#41;;</pre><p> The Material is &quot;somewhere&quot; in the jME3 JAR, but the default Asset Manager is configured to handle a <code>Common/…</code> path correctly, so you don&#039;t have to specify the whole path.</p><p> Additionally, You can configure the Asset Manager and add any path to its root. This means, you can load assets from any project directory you specify.</p><p> <strong>In project created with jMonkeyPlatform, jME3 searches for models in the <code>assets</code> directory of your project by default.</strong> This is our recommended directory structure for storing assets:</p><pre>MyGame/assets/Interface/
<h1><a>AssetManager</a></h1>
<div>
<p>
JME3 has an integrated an asset manager that helps you keep your project assets organized. By assets we mean media files, such as 3D models, materials, textures, scenes, shaders, sounds, and fonts. Think of the asset manager as the filesystem of your game, independent of the actual deployment platform. It also manages the appropriate managing of OpenGL objects like textures so that they are e.g. not uploaded to the graphics card multiple times when multiple models use them.
</p>
<p>
The <code>assetManager</code> object is an com.jme3.asset.AssetManager instance that every com.jme3.app.Application can access. It maintains a root that also includes your project&#039;s classpath by default, so you can load any asset that&#039;s on the classpath, that is, the top level of your project directory.
</p>
<p>
You can use the inherited <code>assetManager</code> object directly, or use the accessor <code>getAssetManager()</code>.
</p>
<p>
Here is an example how you load assets using the AssetManager. This lines loads a default Material from the Common directory:
</p>
<pre>Material mat = &#40;Material&#41; assetManager.loadAsset&#40;
new AssetKey&#40;&quot;Common/Materials/RedColor.j3m&quot;&#41;&#41;;</pre>
<p>
The Material is &quot;somewhere&quot; in the jME3 JAR, but the default Asset Manager is configured to handle a <code>Common/…</code> path correctly, so you don&#039;t have to specify the whole path.
</p>
<p>
Additionally, You can configure the Asset Manager and add any path to its root. This means, you can load assets from any project directory you specify.
</p>
</div>
<h2><a>Asset Folder</a></h2>
<div>
<p>
By default, jME3 searches for models in a directory named <code>assets</code>. <strong>In Java projects created with the jMonkeyPlatform, an assets folder is created by default.</strong> Using any other IDE or the command line, you have to create this assets directory as an extra step (see the Codeless Project tip below).
</p>
<p>
This is our recommended directory structure for storing assets:
</p>
<pre>MyGame/assets/Interface/
MyGame/assets/MatDefs/
MyGame/assets/Materials/
MyGame/assets/Models/
@ -9,65 +50,159 @@ MyGame/assets/Scenes/
MyGame/assets/Shaders/
MyGame/assets/Sounds/
MyGame/assets/Textures/
MyGame/build.xml
MyGame/src/...</pre><p> These are just the most common examples, you can name the directories inside the assets directory how you like.</p></div><h2><a
name="loading_assets">Loading Assets</a></h2><div
class="level2"><pre>// Creating a material instance with the definition &quot;Unshaded.j3md&quot;.
Material mat_brick = new Material&#40;
MyGame/build.xml # build script
MyGame/src/... # source code</pre>
<p>
These are just the most common examples. You can name the directories inside the <code>assets</code> directory what ever you like.
</p>
</div>
<h2><a>Examples: Loading Assets</a></h2>
<div>
<p>
Creating a material instance with the definition &quot;Unshaded.j3md&quot;:
</p>
<pre>Material mat_brick = new Material&#40;
assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
&nbsp;
// Applying a texture to the material
Applying a texture to the material:
&lt;code java&gt;
mat_brick.setTexture&#40;&quot;ColorMap&quot;,
assetManager.loadTexture&#40;&quot;Textures/Terrain/BrickWall/BrickWall.jpg&quot;&#41;&#41;;
&nbsp;
// Loading a font
guiFont = assetManager.loadFont&#40;&quot;Interface/Fonts/Default.fnt&quot;&#41;;
&nbsp;
// Loading a model
Spatial ninja = assetManager.loadModel&#40;&quot;Models/Ninja/Ninja.mesh.xml&quot;&#41;;
&nbsp;
// Loading a scene from an Ogre3D dotScene file stored inside a zip
assetManager.registerLocator&#40;&quot;town.zip&quot;, ZipLocator.class.getName&#40;&#41;&#41;;
assetManager.loadTexture&#40;&quot;Textures/Terrain/BrickWall/BrickWall.jpg&quot;&#41;&#41;;</pre>
<p>
Loading a font:
</p>
<pre>guiFont = assetManager.loadFont&#40;&quot;Interface/Fonts/Default.fnt&quot;&#41;;</pre>
<p>
Loading a model:
</p>
<pre>Spatial ninja = assetManager.loadModel&#40;&quot;Models/Ninja/Ninja.mesh.xml&quot;&#41;;</pre>
<p>
Loading a scene from an Ogre3D dotScene file stored inside a zip:
</p>
<pre>assetManager.registerLocator&#40;&quot;town.zip&quot;, ZipLocator.class.getName&#40;&#41;&#41;;
Spatial scene = assetManager.loadModel&#40;&quot;main.scene&quot;&#41;;
rootNode.attachChild&#40;scene&#41;;</pre><p> Here is a HttpZipLocator that can stream models from a zip file online:</p><pre> assetManager.registerLocator&#40;&quot;http://jmonkeyengine.googlecode.com/files/wildhouse.zip&quot;,
rootNode.attachChild&#40;scene&#41;;</pre>
<p>
Alternatively to ZipLocator, there is also a HttpZipLocator that can stream models from a zip file online:
</p>
<pre>assetManager.registerLocator&#40;&quot;http://jmonkeyengine.googlecode.com/files/wildhouse.zip&quot;,
HttpZipLocator.class.getName&#40;&#41;&#41;;
Spatial scene = assetManager.loadModel&#40;&quot;main.scene&quot;&#41;;
rootNode.attachChild&#40;scene&#41;;</pre><p> JME3 offers ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, and UrlLocator (see <code>com.jme3.asset.plugins</code>).</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0"> Task?</th><th
class="col1"> Solution!</th></tr><tr
class="row1"><td
class="col0"> Load a model with materials</td><td
class="col1"> Use the asset managers <code>loadModel()</code> method and attach the Spatial to the rootNode.<pre>Spatial elephant = assetManager.loadModel&#40;&quot;Models/Elephant/Elephant.mesh.xml&quot;&#41;;
rootNode.attachChild&#40;elephant&#41;;</pre><pre>Spatial elephant = assetManager.loadModel&#40;&quot;Models/Elephant/Elephant.j3o&quot;&#41;;
rootNode.attachChild&#40;elephant&#41;;</pre></td></tr><tr
class="row2"><td
class="col0"> Load a model without materials</td><td
class="col1"> If you have a model without materials, you have to add a default material to make it visible.<pre>Spatial teapot = assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;
Spatial scene = assetManager.loadModel&#40;&quot;main.scene&quot;&#41;;
rootNode.attachChild&#40;scene&#41;;</pre>
<p>
jME3 also offers a ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, and UrlLocator (see <code>com.jme3.asset.plugins</code>).
</p>
<p>
<strong>Note:</strong> The custom build script does not automatically include ZIP files in the executable build.
</p>
</div>
<h2><a>Comon AssetManager Tasks</a></h2>
<div>
<div><table>
<tr>
<th> Task? </th><th> Solution! </th>
</tr>
<tr>
<td> Load a model with materials </td><td> Use the asset manager&#039;s <code>loadModel()</code> method and attach the Spatial to the rootNode. <pre>Spatial elephant = assetManager.loadModel&#40;&quot;Models/Elephant/Elephant.mesh.xml&quot;&#41;;
rootNode.attachChild&#40;elephant&#41;;</pre>
<pre>Spatial elephant = assetManager.loadModel&#40;&quot;Models/Elephant/Elephant.j3o&quot;&#41;;
rootNode.attachChild&#40;elephant&#41;;</pre>
</td>
</tr>
<tr>
<td> Load a model without materials </td><td> If you have a model without materials, you have to add a default material to make it visible. <pre>Spatial teapot = assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/ShowNormals.j3md&quot;&#41;;
teapot.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;teapot&#41;;</pre></td></tr><tr
class="row3"><td
class="col0"> Load a scene</td><td
class="col1"> You load scenes just like you load models:<pre>Spatial scene = assetManager.loadModel&#40;&quot;Scenes/house/main.scene&quot;&#41;;
rootNode.attachChild&#40;scene&#41;;</pre></td></tr></table></div></div><h2><a
name="nullpointerexceptioncannot_locate_resource">NullPointerException: Cannot locate resource?</a></h2><div
class="level2"><p> An error mesage similar to the following can occur in the console when you run executables, even if the game runs fine when started from the jMoneykPlatform.</p><pre>com.jme3.asset.DesktopAssetManager loadAsset
rootNode.attachChild&#40;teapot&#41;;</pre>
</td>
</tr>
<tr>
<td> Load a scene </td><td> You load scenes just like you load models: <pre>Spatial scene = assetManager.loadModel&#40;&quot;Scenes/house/main.scene&quot;&#41;;
rootNode.attachChild&#40;scene&#41;;</pre>
</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3746-4674] -->
</div>
<h2><a>NullPointerException: Cannot locate resource?</a></h2>
<div>
<p>
Even if the game runs fine when started from the jMoneykPlatform, an error message similar to the following can occur in the console when you run the stand-alone executables (.JAR, .JNLP, etc).
</p>
<pre>com.jme3.asset.DesktopAssetManager loadAsset
WARNING: Cannot locate resource: Scenes/town/main.scene
com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException</pre><p> Reason: If you use the default build script created by the jMonkeyPlatform then <strong>the original OgreXML files are not included in the executable.</strong></p><p> For a stand-alone build, you <strong>work with .j3o files only</strong>. The default build script makes sure to include .j3o files in the executable.</p><p> You must use the jMonkeyPlatform&#039;s context menu action to <a
href="/com/jme3/gde/core/docs/jme3/jmonkeyplatform/model_loader_and_viewer.html">convert OgreXML models to .j3o format</a> to get rid of this error.</p><ol><li
class="level1"><div
class="li"> Open the JME3 Project in the jMonkeyplatform.</div></li><li
class="level1"><div
class="li"> Browse the Assets directory in the Projects window.</div></li><li
class="level1"><div
class="li"> Right-click a .mesh.xml file, and choose &quot;convert to JME3 binary&quot;.</div></li><li
class="level1"><div
class="li"> The converted file appears in the same directory as the .mesh.xml file. It has the same name and a .j3o suffix.</div></li></ol></div><h2><a
name="asset_handlingcodeless_projects">Asset Handling: Codeless Projects</a></h2><div
class="level2"><p> If you are using another IDE than jMonkeyPlatform, you can create a codeless project in the jMonkeyPlatform to maintain assets. This method will not meddle with your sources or custom build scripts, but you can still browse your assets, and preview, arrange, and convert models. You can, for example, give the designers in your team access to such a codeless project.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:asset_manager?do=export_xhtmlbody">view online version</a></em></p>
java.lang.NullPointerException</pre>
<p>
<strong>Reason:</strong>
</p>
<p>
If you use the default build script created by the jMonkeyPlatform then <strong>the original OgreXML files are not included in the executable.</strong> A stand-alone executable <strong>works with .j3o files only</strong>. The default build script makes sure to include .j3o files in the executable.
</p>
<p>
<strong>Solution</strong>
</p>
<p>
Before building the executable, you must use the jMonkeyPlatform&#039;s context menu action to <a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">convert OgreXML models to .j3o format</a>.
</p>
<ol>
<li><div> Open the kME3 Project in the jMonkeyplatform.</div>
</li>
<li><div> Browse the <code>assets</code> directory in the Projects window. </div>
</li>
<li><div> Right-click a .mesh.xml or .obj or .scene file, and choose &quot;convert to JME3 binary&quot;. </div>
</li>
<li><div> The converted file appears in the same directory as the .mesh.xml file. It has the same name and a .j3o suffix. </div>
</li>
<li><div> Make sure to change the loading code to load the file with a .j3o suffix now.</div>
</li>
</ol>
<p>
If you load the scene from a non.j3o ZIP file, expand the <a href="/com/jme3/gde/core/docs/sdk/default_build_script.html">default_build_script</a> to copy the ZIP files.
</p>
</div>
<h2><a>Asset Handling: Codeless Projects</a></h2>
<div>
<p>
If you are using another IDE than jMonkeyPlatform for coding, you should create a so-called codeless project in the jMonkeyPlatform to maintain assets. This method will not meddle with your sources or custom build scripts. It simply makes it easier for you to browse game assets, and preview, arrange, and especially convert models to binary.
</p>
<ul>
<li><div> You use your favorite IDE to code and use the jMonkeyPlatform only for jME3 assets maintenance.</div>
</li>
<li><div> You can also ask the graphic designers in your team to install the jMonkeyPlatform and give them access to such a codeless project.</div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:asset_manager?do=export_xhtmlbody">view online version</a></em></p>

@ -1,141 +1,187 @@
<h1><a
name="audio_in_jme3">Audio in jME3</a></h1><div
class="level1"><p> There are two ways to handle audio data: Short audio files are to be stored entirely in memory, while long audio files (music) is streamed from the hard drive as it is played.
Place audio files in the <code>assets/Sound/</code> directory of your project. jME3 supports Ogg Vorbis (.ogg) and Wave (.wav) formats.</p></div><h2><a
name="creating_audio_nodes">Creating Audio Nodes</a></h2><div
class="level2"><p> The main class to look at is <code>com.jme3.audio.AudioNode</code>.
By default, a new audio node is buffered, i.e. JME loads the whole file into memory before playing:</p><pre>AudioNode boom = new AudioNode&#40;audioRenderer, assetManager, &quot;Sound/boom.wav&quot;&#41;;</pre><p> If it is a long file, you set the boolean to true to stream the audio.</p><pre>AudioNode music = new AudioNode&#40;audioRenderer, assetManager, &quot;Sound/music.wav&quot;, true&#41;;</pre></div><h2><a
name="setting_audionode_properties">Setting AudioNode Properties</a></h2><div
class="level2"><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">AudioNode Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">getStatus()</td><td
class="col1">Returns either Status.Playing, Status.Stopped, or Status.Paused.</td></tr><tr
class="row2"><td
class="col0">setVolume(1)</td><td
class="col1">Sets the volume gain. 1 is the default volume, 2 is twice as loud, 0 is mute.</td></tr><tr
class="row3"><td
class="col0">setPitch(1)</td><td
class="col1">Makes the sound play in a higher or lower pitch. Default is 1.</td></tr><tr
class="row4"><th
class="col0">AudioNode Method</th><th
class="col1">Usage</th></tr><tr
class="row5"><td
class="col0">setLooping(false)</td><td
class="col1">Configures the sound that, if it is played, it plays once and stops. This is the default.</td></tr><tr
class="row6"><td
class="col0">setLooping(true)</td><td
class="col1 leftalign">Configures the sound that, if it is played, it plays repeats from the beginning, until stop() or pause() are called. Good for ambient background noises.</td></tr><tr
class="row7"><td
class="col0">setPositional(false) <br/> setDirectional(false)</td><td
class="col1">All 3D effects switched off. This sound is global and comes from everywhere. Good for environmental ambient sounds and background music.</td></tr><tr
class="row8"><td
class="col0">setTimeOffset(0.5f)</td><td
class="col1">Start playing the sound after waiting the given amount of seconds. Default is 0.</td></tr><tr
class="row9"><td
class="col0">setMaxDistance(100f)</td><td
class="col1">Maximum distance the sound can be heard, in world units. Default is 20.</td></tr><tr
class="row10"><th
class="col0">AudioNode Method</th><th
class="col1">Usage</th></tr><tr
class="row11"><td
class="col0">setPositional(true) <br/> setLocalTranslation(new Vector 3f(0,0,0))</td><td
class="col1">Activates 3D audio, the sound appears to come from a certain position, where it is loudest. Position the AudioNode in the 3D scene if you have setPositional() true. Position it with mobile players or NPCs.</td></tr><tr
class="row12"><td
class="col0">setReverbEnabled(true)</td><td
class="col1">A 3D echo effect that only makes sense to use with moving positional AudioNodes. The reverb effect is influenced by the environment that the audio renderer is in. See &quot;Setting Environment Properties&quot; below.</td></tr><tr
class="row13"><th
class="col0">AudioNode Method</th><th
class="col1">Usage</th></tr><tr
class="row14"><td
class="col0">setDirectional(true) <br/> setDirection(new Vector3f(0,0,1))</td><td
class="col1">Activates 3D audio. This sound can only be heard from a certain direction. Specify the direction and angle in the 3D scene if you have setDirectional() true. Good for noises that should not be heard through a wall.</td></tr><tr
class="row15"><td
class="col0">setInnerAngle() <br/> setOuterAngle()</td><td
class="col1">Set the angle in degrees for the directional audio. The angle is relative to the direction. By default, both angles are 360° and the sound can be heard from all directions.</td></tr></table></div></div><h2><a
name="play_pause_stop">Play, Pause, Stop</a></h2><div
class="level2"><p> You play, pause, and stop a node called myAudioNode by using the respective of the following three methods:</p><pre>myAudioNode.play&#40;&#41;;</pre><pre>myAudioNode.pause&#40;&#41;;</pre><pre>myAudioNode.stop&#40;&#41;;</pre><p> <strong>Note:</strong> Whether an Audio Node plays continuously or only once, depends on the Loop properties you have set above!</p></div><h2><a
name="setting_environment_properties">Setting Environment Properties</a></h2><div
class="level2"><p> Optionally, You can choose from the following environmental presets from <code>com.jme3.audio.Environment</code>. This presets influence subtle echo effects that evoke associations of different environments in your users. You use it together with setReverbEnbaled(true) mentioned above.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">Environment</th><th
class="col1">density</th><th
class="col2">diffusion</th><th
class="col3">gain</th><th
class="col4">gainHf</th><th
class="col5">decayTime</th><th
class="col6">decayHf</th><th
class="col7">reflGain</th><th
class="col8">reflDelay</th><th
class="col9">lateGain</th><th
class="col10">lateDelay</th></tr><tr
class="row1"><td
class="col0 leftalign">Garage</td><td
class="col1">1.00f</td><td
class="col2">1.0f</td><td
class="col3">1.0f</td><td
class="col4">1.00f</td><td
class="col5">0.90f</td><td
class="col6">0.5f</td><td
class="col7">0.751f</td><td
class="col8">0.0039f</td><td
class="col9">0.661f</td><td
class="col10">0.0137f</td></tr><tr
class="row2"><td
class="col0 leftalign">Dungeon</td><td
class="col1">0.75f</td><td
class="col2">1.0f</td><td
class="col3">1.0f</td><td
class="col4">0.75f</td><td
class="col5">1.60f</td><td
class="col6">1.0f</td><td
class="col7">0.950f</td><td
class="col8">0.0026f</td><td
class="col9">0.930f</td><td
class="col10">0.0103f</td></tr><tr
class="row3"><td
class="col0 leftalign">Cavern</td><td
class="col1">0.50f</td><td
class="col2">1.0f</td><td
class="col3">1.0f</td><td
class="col4">0.50f</td><td
class="col5">2.25f</td><td
class="col6">1.0f</td><td
class="col7">0.908f</td><td
class="col8">0.0103f</td><td
class="col9">0.930f</td><td
class="col10">0.0410f</td></tr><tr
class="row4"><td
class="col0">AcousticLab</td><td
class="col1">0.50f</td><td
class="col2">1.0f</td><td
class="col3">1.0f</td><td
class="col4">1.00f</td><td
class="col5">0.28f</td><td
class="col6">1.0f</td><td
class="col7">0.870f</td><td
class="col8">0.0020f</td><td
class="col9">0.810f</td><td
class="col10">0.0080f</td></tr><tr
class="row5"><td
class="col0 leftalign">Closet</td><td
class="col1">1.00f</td><td
class="col2">1.0f</td><td
class="col3">1.0f</td><td
class="col4">1.00f</td><td
class="col5">0.15f</td><td
class="col6">1.0f</td><td
class="col7">0.600f</td><td
class="col8">0.0025f</td><td
class="col9">0.500f</td><td
class="col10">0.0006f</td></tr></table></div><p> Activate the preset with setEnvironment(). E.g. in a dungeon environment:</p><pre>audioRenderer.setEnvironment&#40;new Environment.Dungeon&#41;&#41;;</pre><p> A sound engineer can create a custom <code>com.jme3.audio.Environment</code> object and specify custom environment factors. Activate your custom environment settings in the Environment constructor:</p><pre>audioRenderer.setEnvironment&#40;
<h1><a>Audio in jME3</a></h1>
<div>
<p>
There are two ways to handle audio data: Short audio files are to be stored entirely in memory, while long audio files (music) is streamed from the hard drive as it is played.
</p>
<p>
Place audio files in the <code>assets/Sound/</code> directory of your project. jME3 supports Ogg Vorbis (.ogg) and Wave (.wav) formats.
</p>
</div>
<h2><a>Creating Audio Nodes</a></h2>
<div>
<p>
The main class to look at is <code>com.jme3.audio.AudioNode</code>.
By default, a new audio node is buffered, i.e. JME loads the whole file into memory before playing:
</p>
<pre>AudioNode boom = new AudioNode&#40;assetManager, &quot;Sound/boom.wav&quot;&#41;;</pre>
<p>
If it is a long file, you set the boolean to true to stream the audio.
</p>
<pre>AudioNode music = new AudioNode&#40;assetManager, &quot;Sound/music.wav&quot;, true&#41;;</pre>
</div>
<h2><a>Setting AudioNode Properties</a></h2>
<div>
<div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>getStatus()</td><td>Returns either Status.Playing, Status.Stopped, or Status.Paused.</td>
</tr>
<tr>
<td>setVolume(1)</td><td>Sets the volume gain. 1 is the default volume, 2 is twice as loud, 0 is mute. </td>
</tr>
<tr>
<td>setPitch(1)</td><td>Makes the sound play in a higher or lower pitch. Default is 1.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [814-1088] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>setLooping(false)</td><td>Configures the sound that, if it is played, it plays once and stops. This is the default.</td>
</tr>
<tr>
<td>setLooping(true)</td><td>Configures the sound that, if it is played, it plays repeats from the beginning, until stop() or pause() are called. Good for ambient background noises. </td>
</tr>
<tr>
<td>setPositional(false) <br/>
setDirectional(false)</td><td>All 3D effects switched off. This sound is global and comes from everywhere. Good for environmental ambient sounds and background music.</td>
</tr>
<tr>
<td>setTimeOffset(0.5f)</td><td>Start playing the sound after waiting the given amount of seconds. Default is 0.</td>
</tr>
<tr>
<td>setMaxDistance(100f)</td><td>Maximum distance the sound can be heard, in world units. Default is 20.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [1090-1781] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>setPositional(true) <br/>
setLocalTranslation(…)</td><td>Activates 3D audio: The sound appears to come from a certain position, where it is loudest. Position the AudioNode in the 3D scene, or move it with mobile players or NPCs.</td>
</tr>
<tr>
<td>setReverbEnabled(true)</td><td>A 3D echo effect that only makes sense to use with positional AudioNodes. The reverb effect is influenced by the environment that the audio renderer is in. See &quot;Setting Environment Properties&quot; below. </td>
</tr>
</table></div>
<!-- EDIT3 TABLE [1783-2255] --><div><table>
<tr>
<th>AudioNode Method</th><th>Usage</th>
</tr>
<tr>
<td>setDirectional(true) <br/>
setDirection(…) </td><td>Activates 3D audio: This sound can only be heard from a certain direction. Specify the direction and angle in the 3D scene if you have setDirectional() true. Use this to restrict noises that should not be heard, for example, through a wall.</td>
</tr>
<tr>
<td>setInnerAngle() <br/>
setOuterAngle()</td><td>Set the angle in degrees for the directional audio. The angle is relative to the direction. Note: By default, both angles are 360° and the sound can be heard from all directions!</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [2257-2784] -->
</div>
<h2><a>Play, Pause, Stop</a></h2>
<div>
<p>
You play, pause, and stop a node called myAudioNode by using the respective of the following three methods:
</p>
<pre>myAudioNode.play&#40;&#41;;</pre>
<pre>myAudioNode.pause&#40;&#41;;</pre>
<pre>myAudioNode.stop&#40;&#41;;</pre>
<p>
<strong>Note:</strong> Whether an Audio Node plays continuously or only once, depends on the Loop properties you have set above!
</p>
<p>
You can also start playing an instance of this AudioNode. Use the playInstance() method if you need to play the same AudioNode multiple times, possibly simulatenously. Note that changes to the parameters of the original AudioNode do not affect the instances that are already playing!
</p>
<pre>myAudioNode.playInstance&#40;&#41;;</pre>
</div>
<h2><a>The Listener</a></h2>
<div>
<p>
The default listener object is the user&#039;s ear in the scene. If you use positional audio, you have to move the listener with the player: For example, for a first-person player, you move the listener with the camera. For a third-person player, you move the listener with the player avatar Geometry.
</p>
<pre> @Override
public void simpleUpdate&#40;float tpf&#41; &#123;
// keep the audio listener moving with the camera
listener.setLocation&#40;cam.getLocation&#40;&#41;&#41;;
listener.setRotation&#40;cam.getRotation&#40;&#41;&#41;;
&#125;</pre>
</div>
<h2><a>Setting Environment Properties</a></h2>
<div>
<p>
Optionally, You can choose from the following environmental presets from <code>com.jme3.audio.Environment</code>. This presets influence subtle echo effects that evoke associations of different environments in your users. You use it together with setReverbEnabled(true) mentioned above.
</p>
<div><table>
<tr>
<th>Environment</th><th>density</th><th>diffusion</th><th>gain</th><th>gainHf</th><th>decayTime</th><th>decayHf</th><th>reflGain</th><th>reflDelay</th><th>lateGain</th><th>lateDelay</th>
</tr>
<tr>
<td>Garage </td><td>1.00f</td><td>1.0f</td><td>1.0f</td><td>1.00f</td><td>0.90f</td><td>0.5f</td><td>0.751f</td><td>0.0039f</td><td>0.661f</td><td>0.0137f</td>
</tr>
<tr>
<td>Dungeon </td><td>0.75f</td><td>1.0f</td><td>1.0f</td><td>0.75f</td><td>1.60f</td><td>1.0f</td><td>0.950f</td><td>0.0026f</td><td>0.930f</td><td>0.0103f</td>
</tr>
<tr>
<td>Cavern </td><td>0.50f</td><td>1.0f</td><td>1.0f</td><td>0.50f</td><td>2.25f</td><td>1.0f</td><td>0.908f</td><td>0.0103f</td><td>0.930f</td><td>0.0410f</td>
</tr>
<tr>
<td>AcousticLab </td><td>0.50f</td><td>1.0f</td><td>1.0f</td><td>1.00f</td><td>0.28f</td><td>1.0f</td><td>0.870f</td><td>0.0020f</td><td>0.810f</td><td>0.0080f</td>
</tr>
<tr>
<td>Closet </td><td>1.00f</td><td>1.0f</td><td>1.0f</td><td>1.00f</td><td>0.15f</td><td>1.0f</td><td>0.600f</td><td>0.0025f</td><td>0.500f</td><td>0.0006f</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [4359-4848] -->
<p>
Activate the preset with setEnvironment(). E.g. in a dungeon environment:
</p>
<pre>audioRenderer.setEnvironment&#40;new Environment.Dungeon&#41;&#41;;</pre>
<p>
A sound engineer can create a custom <code>com.jme3.audio.Environment</code> object and specify custom environment factors. You can find many <a href="/com/jme3/gde/core/docs/jme3/advanced/audio_environment_presets.html">examples of audio environment presets</a> here. Activate your custom environment settings in the Environment constructor:
</p>
<pre>audioRenderer.setEnvironment&#40;
new Environment&#40; density, diffusion, gain, gainHf, decayTime, decayHf,
reflGain, reflDelay, lateGain, lateDelay &#41; &#41;;</pre><p> You can find more info about OpenAL and its advanced features here: <a
href="http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.pdf">OpenAL 1.1 Specification</a></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:audio?do=export_xhtmlbody">view online version</a></em></p>
reflGain, reflDelay, lateGain, lateDelay &#41; &#41;;</pre>
<p>
You can find more info about OpenAL and its advanced features here: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.pdf"><param name="text" value="<html><u>OpenAL 1.1 Specification</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:audio?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,212 @@
<h1><a>Audio Environment Presets</a></h1>
<div>
<p>
Use these presets together with <a href="/com/jme3/gde/core/docs/jme3/advanced/audio.html">Audio</a> Nodes to create different &quot;moods&quot; for sounds. Environment effects make your audio sound as if the listener were in various places that have different types of echoes.
</p>
<p>
Usage:
</p>
<pre>Environment&#40;
new float&#91;&#93;&#123; 0, 7.5f, 1f, -1000, -100, 0, 1.49f, 0.83f, 1f, -2602,
0.007f, 0f, 0f, 0f, 200, 0.011f, 0f, 0f, 0f, 0.250f,
0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
audioRenderer.setEnvironment&#40;myEnvironment&#41;;</pre>
</div>
<h2><a>Castle</a></h2>
<div>
<pre>CastleSmallRoom = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.890f, -1000, -800, -2000, 1.22f, 0.83f, 0.31f, -100, 0.022f, 0f, 0f, 0f, 600, 0.011f, 0f, 0f, 0f, 0.138f, 0.080f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleShortPassage = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.890f, -1000, -1000, -2000, 2.32f, 0.83f, 0.31f, -100, 0.007f, 0f, 0f, 0f, 200, 0.023f, 0f, 0f, 0f, 0.138f, 0.080f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleMediumroom = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.930f, -1000, -1100, -2000, 2.04f, 0.83f, 0.46f, -400, 0.022f, 0f, 0f, 0f, 400, 0.011f, 0f, 0f, 0f, 0.155f, 0.030f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleLongpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.890f, -1000, -800, -2000, 3.42f, 0.83f, 0.31f, -100, 0.007f, 0f, 0f, 0f, 300, 0.023f, 0f, 0f, 0f, 0.138f, 0.080f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleLargeroom = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.820f, -1000, -1100, -1800, 2.53f, 0.83f, 0.50f, -700, 0.034f, 0f, 0f, 0f, 200, 0.016f, 0f, 0f, 0f, 0.185f, 0.070f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleHall = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.810f, -1000, -1100, -1500, 3.14f, 0.79f, 0.62f, -1500, 0.056f, 0f, 0f, 0f, 100, 0.024f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleCupboard = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.890f, -1000, -1100, -2000, 0.67f, 0.87f, 0.31f, 300, 0.010f, 0f, 0f, 0f, 1100, 0.007f, 0f, 0f, 0f, 0.138f, 0.080f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;
CastleCourtyard = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.420f, -1000, -700, -1400, 2.13f, 0.61f, 0.23f, -1300, 0.160f, 0f, 0f, 0f, -300, 0.036f, 0f, 0f, 0f, 0.250f, 0.370f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
CastleAlcove = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 0.890f, -1000, -600, -2000, 1.64f, 0.87f, 0.31f, 00, 0.007f, 0f, 0f, 0f, 300, 0.034f, 0f, 0f, 0f, 0.138f, 0.080f, 0.250f, 0f, -5f, 5168.6f, 139.5f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Warehouse, Factory</a></h2>
<div>
<pre>FactoryAlcove = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.590f, -1200, -200, -600, 3.14f, 0.65f, 1.31f, 300, 0.010f, 0f, 0f, 0f, 000, 0.038f, 0f, 0f, 0f, 0.114f, 0.100f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryShortpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.640f, -1200, -200, -600, 2.53f, 0.65f, 1.31f, 0, 0.010f, 0f, 0f, 0f, 200, 0.038f, 0f, 0f, 0f, 0.135f, 0.230f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryMediumroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.820f, -1200, -200, -600, 2.76f, 0.65f, 1.31f, -1100, 0.022f, 0f, 0f, 0f, 300, 0.023f, 0f, 0f, 0f, 0.174f, 0.070f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryLongpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.640f, -1200, -200, -600, 4.06f, 0.65f, 1.31f, 0, 0.020f, 0f, 0f, 0f, 200, 0.037f, 0f, 0f, 0f, 0.135f, 0.230f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryLargeroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.750f, -1200, -300, -400, 4.24f, 0.51f, 1.31f, -1500, 0.039f, 0f, 0f, 0f, 100, 0.023f, 0f, 0f, 0f, 0.231f, 0.070f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryHall = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.750f, -1000, -300, -400, 7.43f, 0.51f, 1.31f, -2400, 0.073f, 0f, 0f, 0f, -100, 0.027f, 0f, 0f, 0f, 0.250f, 0.070f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryCupboard = new Environment &#40; new float&#91;&#93;&#123; 26, 1.7f, 0.630f, -1200, -200, -600, 0.49f, 0.65f, 1.31f, 200, 0.010f, 0f, 0f, 0f, 600, 0.032f, 0f, 0f, 0f, 0.107f, 0.070f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactoryCourtyard = new Environment &#40; new float&#91;&#93;&#123; 26, 1.7f, 0.570f, -1000, -1000, -400, 2.32f, 0.29f, 0.56f, -1300, 0.140f, 0f, 0f, 0f, -800, 0.039f, 0f, 0f, 0f, 0.250f, 0.290f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;
FactorySmallroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.820f, -1000, -200, -600, 1.72f, 0.65f, 1.31f, -300, 0.010f, 0f, 0f, 0f, 500, 0.024f, 0f, 0f, 0f, 0.119f, 0.070f, 0.250f, 0f, -5f, 3762.6f, 362.5f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Ice Palace</a></h2>
<div>
<pre>IcepalaceAlcove = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.840f, -1000, -500, -1100, 2.76f, 1.46f, 0.28f, 100, 0.010f, 0f, 0f, 0f, -100, 0.030f, 0f, 0f, 0f, 0.161f, 0.090f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceShortpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.750f, -1000, -500, -1100, 1.79f, 1.46f, 0.28f, -600, 0.010f, 0f, 0f, 0f, 100, 0.019f, 0f, 0f, 0f, 0.177f, 0.090f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceMediumroom = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.870f, -1000, -500, -700, 2.22f, 1.53f, 0.32f, -800, 0.039f, 0f, 0f, 0f, 100, 0.027f, 0f, 0f, 0f, 0.186f, 0.120f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceLongpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.770f, -1000, -500, -800, 3.01f, 1.46f, 0.28f, -200, 0.012f, 0f, 0f, 0f, 200, 0.025f, 0f, 0f, 0f, 0.186f, 0.040f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceLargeroom = new Environment &#40; new float&#91;&#93;&#123; 26, 2.9f, 0.810f, -1000, -500, -700, 3.14f, 1.53f, 0.32f, -1200, 0.039f, 0f, 0f, 0f, 000, 0.027f, 0f, 0f, 0f, 0.214f, 0.110f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceHall = new Environment &#40; new float&#91;&#93;&#123; 26, 2.9f, 0.760f, -1000, -700, -500, 5.49f, 1.53f, 0.38f, -1900, 0.054f, 0f, 0f, 0f, -400, 0.052f, 0f, 0f, 0f, 0.226f, 0.110f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceCupboard = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.830f, -1000, -600, -1300, 0.76f, 1.53f, 0.26f, 100, 0.012f, 0f, 0f, 0f, 600, 0.016f, 0f, 0f, 0f, 0.143f, 0.080f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceCourtyard = new Environment &#40; new float&#91;&#93;&#123; 26, 2.9f, 0.590f, -1000, -1100, -1000, 2.04f, 1.20f, 0.38f, -1000, 0.173f, 0f, 0f, 0f, -1000, 0.043f, 0f, 0f, 0f, 0.235f, 0.480f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;
IcepalaceSmallroom = new Environment &#40; new float&#91;&#93;&#123; 26, 2.7f, 0.840f, -1000, -500, -1100, 1.51f, 1.53f, 0.27f, -100, 0.010f, 0f, 0f, 0f, 300, 0.011f, 0f, 0f, 0f, 0.164f, 0.140f, 0.250f, 0f, -5f, 12428.5f, 99.6f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Space Station</a></h2>
<div>
<pre>SpacestationAlcove = new Environment &#40; new float&#91;&#93;&#123; 26, 1.5f, 0.780f, -1000, -300, -100, 1.16f, 0.81f, 0.55f, 300, 0.007f, 0f, 0f, 0f, 000, 0.018f, 0f, 0f, 0f, 0.192f, 0.210f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationMediumroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.5f, 0.750f, -1000, -400, -100, 3.01f, 0.50f, 0.55f, -800, 0.034f, 0f, 0f, 0f, 100, 0.035f, 0f, 0f, 0f, 0.209f, 0.310f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationShortpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 1.5f, 0.870f, -1000, -400, -100, 3.57f, 0.50f, 0.55f, 0, 0.012f, 0f, 0f, 0f, 100, 0.016f, 0f, 0f, 0f, 0.172f, 0.200f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationLongpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.820f, -1000, -400, -100, 4.62f, 0.62f, 0.55f, 0, 0.012f, 0f, 0f, 0f, 200, 0.031f, 0f, 0f, 0f, 0.250f, 0.230f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationLargeroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.810f, -1000, -400, -100, 3.89f, 0.38f, 0.61f, -1000, 0.056f, 0f, 0f, 0f, -100, 0.035f, 0f, 0f, 0f, 0.233f, 0.280f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationHall = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.870f, -1000, -400, -100, 7.11f, 0.38f, 0.61f, -1500, 0.100f, 0f, 0f, 0f, -400, 0.047f, 0f, 0f, 0f, 0.250f, 0.250f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationCupboard = new Environment &#40; new float&#91;&#93;&#123; 26, 1.4f, 0.560f, -1000, -300, -100, 0.79f, 0.81f, 0.55f, 300, 0.007f, 0f, 0f, 0f, 500, 0.018f, 0f, 0f, 0f, 0.181f, 0.310f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;
SpacestationSmallroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.5f, 0.700f, -1000, -300, -100, 1.72f, 0.82f, 0.55f, -200, 0.007f, 0f, 0f, 0f, 300, 0.013f, 0f, 0f, 0f, 0.188f, 0.260f, 0.250f, 0f, -5f, 3316.1f, 458.2f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Wooden Hut or Ship</a></h2>
<div>
<pre>WoodenAlcove = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -1800, -1000, 1.22f, 0.62f, 0.91f, 100, 0.012f, 0f, 0f, 0f, -300, 0.024f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenShortpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -1800, -1000, 1.75f, 0.50f, 0.87f, -100, 0.012f, 0f, 0f, 0f, -400, 0.024f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenMediumroom = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -2000, -1100, 1.47f, 0.42f, 0.82f, -100, 0.049f, 0f, 0f, 0f, -100, 0.029f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenLongpassage = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -2000, -1000, 1.99f, 0.40f, 0.79f, 000, 0.020f, 0f, 0f, 0f, -700, 0.036f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenLargeroom = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -2100, -1100, 2.65f, 0.33f, 0.82f, -100, 0.066f, 0f, 0f, 0f, -200, 0.049f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenHall = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -2200, -1100, 3.45f, 0.30f, 0.82f, -100, 0.088f, 0f, 0f, 0f, -200, 0.063f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenCupboard = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -1700, -1000, 0.56f, 0.46f, 0.91f, 100, 0.012f, 0f, 0f, 0f, 100, 0.028f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenSmallroom = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 1f, -1000, -1900, -1000, 0.79f, 0.32f, 0.87f, 00, 0.032f, 0f, 0f, 0f, -100, 0.029f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;
WoodenCourtyard = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 0.650f, -1000, -2200, -1000, 1.79f, 0.35f, 0.79f, -500, 0.123f, 0f, 0f, 0f, -2000, 0.032f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 4705f, 99.6f, 0f, 0x3f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Sport</a></h2>
<div>
<pre>SportEmptystadium = new Environment &#40; new float&#91;&#93;&#123; 26, 7.2f, 1f, -1000, -700, -200, 6.26f, 0.51f, 1.10f, -2400, 0.183f, 0f, 0f, 0f, -800, 0.038f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;
SportSquashcourt = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 0.750f, -1000, -1000, -200, 2.22f, 0.91f, 1.16f, -700, 0.007f, 0f, 0f, 0f, -200, 0.011f, 0f, 0f, 0f, 0.126f, 0.190f, 0.250f, 0f, -5f, 7176.9f, 211.2f, 0f, 0x20&#125; &#41; &#41;;
SportSmallswimmingpool = new Environment &#40; new float&#91;&#93;&#123; 26, 36.2f, 0.700f, -1000, -200, -100, 2.76f, 1.25f, 1.14f, -400, 0.020f, 0f, 0f, 0f, -200, 0.030f, 0f, 0f, 0f, 0.179f, 0.150f, 0.895f, 0.190f, -5f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;
SportLargeswimmingpool = new Environment &#40; new float&#91;&#93;&#123; 26, 36.2f, 0.820f, -1000, -200, 0, 5.49f, 1.31f, 1.14f, -700, 0.039f, 0f, 0f, 0f, -600, 0.049f, 0f, 0f, 0f, 0.222f, 0.550f, 1.159f, 0.210f, -5f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;
SportGymnasium = new Environment &#40; new float&#91;&#93;&#123; 26, 7.5f, 0.810f, -1000, -700, -100, 3.14f, 1.06f, 1.35f, -800, 0.029f, 0f, 0f, 0f, -500, 0.045f, 0f, 0f, 0f, 0.146f, 0.140f, 0.250f, 0f, -5f, 7176.9f, 211.2f, 0f, 0x20&#125; &#41; &#41;;
SportFullstadium = new Environment &#40; new float&#91;&#93;&#123; 26, 7.2f, 1f, -1000, -2300, -200, 5.25f, 0.17f, 0.80f, -2000, 0.188f, 0f, 0f, 0f, -1100, 0.038f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Pipes</a></h2>
<div>
<pre>Sewerpipe = new Environment &#40; new float&#91;&#93;&#123; 21, 1.7f, 0.800f, -1000, -1000, 0, 2.81f, 0.14f, 1f, 429, 0.014f, 0f, 0f, 0f, 1023, 0.021f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
PipeSmall = new Environment &#40; new float&#91;&#93;&#123; 26, 50.3f, 1f, -1000, -900, -1300, 5.04f, 0.10f, 0.10f, -600, 0.032f, 0f, 0f, 0f, 800, 0.015f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x3f&#125; &#41; &#41;;
PipeLongthin = new Environment &#40; new float&#91;&#93;&#123; 26, 1.6f, 0.910f, -1000, -700, -1100, 9.21f, 0.18f, 0.10f, -300, 0.010f, 0f, 0f, 0f, -300, 0.022f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x0&#125; &#41; &#41;;
PipeLarge = new Environment &#40; new float&#91;&#93;&#123; 26, 50.3f, 1f, -1000, -900, -1300, 8.45f, 0.10f, 0.10f, -800, 0.046f, 0f, 0f, 0f, 400, 0.032f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x3f&#125; &#41; &#41;;
PipeResonant = new Environment &#40; new float&#91;&#93;&#123; 26, 1.3f, 0.910f, -1000, -700, -1100, 6.81f, 0.18f, 0.10f, -300, 0.010f, 0f, 0f, 0f, 00, 0.022f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x0&#125; &#41; &#41;;</pre>
</div>
<h2><a>Moods</a></h2>
<div>
<pre>Heaven = new Environment &#40; new float&#91;&#93;&#123; 26, 19.6f, 0.940f, -1000, -200, -700, 5.04f, 1.12f, 0.56f, -1230, 0.020f, 0f, 0f, 0f, 200, 0.029f, 0f, 0f, 0f, 0.250f, 0.080f, 2.742f, 0.050f, -2f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Hell = new Environment &#40; new float&#91;&#93;&#123; 26, 100f, 0.570f, -1000, -900, -700, 3.57f, 0.49f, 2f, -10000, 0.020f, 0f, 0f, 0f, 300, 0.030f, 0f, 0f, 0f, 0.110f, 0.040f, 2.109f, 0.520f, -5f, 5000f, 139.5f, 0f, 0x40&#125; &#41; &#41;;
Memory = new Environment &#40; new float&#91;&#93;&#123; 26, 8f, 0.850f, -1000, -400, -900, 4.06f, 0.82f, 0.56f, -2800, 0f, 0f, 0f, 0f, 100, 0f, 0f, 0f, 0f, 0.250f, 0f, 0.474f, 0.450f, -10f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;
Drugged = new Environment &#40; new float&#91;&#93;&#123; 23, 1.9f, 0.500f, -1000, 0, 0, 8.39f, 1.39f, 1f, -115, 0.002f, 0f, 0f, 0f, 985, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 1f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
Dizzy = new Environment &#40; new float&#91;&#93;&#123; 24, 1.8f, 0.600f, -1000, -400, 0, 17.23f, 0.56f, 1f, -1713, 0.020f, 0f, 0f, 0f, -613, 0.030f, 0f, 0f, 0f, 0.250f, 1f, 0.810f, 0.310f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
Psychotic = new Environment &#40; new float&#91;&#93;&#123; 25, 1f, 0.500f, -1000, -151, 0, 7.56f, 0.91f, 1f, -626, 0.020f, 0f, 0f, 0f, 774, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 4f, 1f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Car Racing</a></h2>
<div>
<pre>DrivingCommentator = new Environment &#40; new float&#91;&#93;&#123; 26, 3f, 0f, 1000, -500, -600, 2.42f, 0.88f, 0.68f, -1400, 0.093f, 0f, 0f, 0f, -1200, 0.017f, 0f, 0f, 0f, 0.250f, 1f, 0.250f, 0f, -10f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;
DrivingPitgarage = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 0.590f, -1000, -300, -500, 1.72f, 0.93f, 0.87f, -500, 0f, 0f, 0f, 0f, 200, 0.016f, 0f, 0f, 0f, 0.250f, 0.110f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;
DrivingIncarRacer = new Environment &#40; new float&#91;&#93;&#123; 26, 1.1f, 0.800f, -1000, 0, -200, 0.17f, 2f, 0.41f, 500, 0.007f, 0f, 0f, 0f, -300, 0.015f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 10268.2f, 251f, 0f, 0x20&#125; &#41; &#41;;
DrivingIncarSports = new Environment &#40; new float&#91;&#93;&#123; 26, 1.1f, 0.800f, -1000, -400, 0, 0.17f, 0.75f, 0.41f, 0, 0.010f, 0f, 0f, 0f, -500, 0f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 10268.2f, 251f, 0f, 0x20&#125; &#41; &#41;;
DrivingIncarLuxury = new Environment &#40; new float&#91;&#93;&#123; 26, 1.6f, 1f, -1000, -2000, -600, 0.13f, 0.41f, 0.46f, -200, 0.010f, 0f, 0f, 0f, 400, 0.010f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 10268.2f, 251f, 0f, 0x20&#125; &#41; &#41;;
DrivingFullgrandstand = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 1f, -1000, -1100, -400, 3.01f, 1.37f, 1.28f, -900, 0.090f, 0f, 0f, 0f, -1500, 0.049f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 10420.2f, 250f, 0f, 0x1f&#125; &#41; &#41;;
DrivingEmptygrandstand = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 1f, -1000, 0, -200, 4.62f, 1.75f, 1.40f, -1363, 0.090f, 0f, 0f, 0f, -1200, 0.049f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 10420.2f, 250f, 0f, 0x1f&#125; &#41; &#41;;
DrivingTunnel = new Environment &#40; new float&#91;&#93;&#123; 26, 3.1f, 0.810f, -1000, -800, -100, 3.42f, 0.94f, 1.31f, -300, 0.051f, 0f, 0f, 0f, -300, 0.047f, 0f, 0f, 0f, 0.214f, 0.050f, 0.250f, 0f, -5f, 5000f, 155.3f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>City</a></h2>
<div>
<pre>CityIndoors = new Environment &#40; new float&#91;&#93;&#123; 16, 7.5f, 0.500f, -1000, -800, 0, 1.49f, 0.67f, 1f, -2273, 0.007f, 0f, 0f, 0f, -1691, 0.011f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
CityStreets = new Environment &#40; new float&#91;&#93;&#123; 26, 3f, 0.780f, -1000, -300, -100, 1.79f, 1.12f, 0.91f, -1100, 0.046f, 0f, 0f, 0f, -1400, 0.028f, 0f, 0f, 0f, 0.250f, 0.200f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;
CitySubway = new Environment &#40; new float&#91;&#93;&#123; 26, 3f, 0.740f, -1000, -300, -100, 3.01f, 1.23f, 0.91f, -300, 0.046f, 0f, 0f, 0f, 200, 0.028f, 0f, 0f, 0f, 0.125f, 0.210f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;
CityMuseum = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.820f, -1000, -1500, -1500, 3.28f, 1.40f, 0.57f, -1200, 0.039f, 0f, 0f, -0f, -100, 0.034f, 0f, 0f, 0f, 0.130f, 0.170f, 0.250f, 0f, -5f, 2854.4f, 107.5f, 0f, 0x0&#125; &#41; &#41;;
CityLibrary = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.820f, -1000, -1100, -2100, 2.76f, 0.89f, 0.41f, -900, 0.029f, 0f, 0f, -0f, -100, 0.020f, 0f, 0f, 0f, 0.130f, 0.170f, 0.250f, 0f, -5f, 2854.4f, 107.5f, 0f, 0x0&#125; &#41; &#41;;
CityUnderpass = new Environment &#40; new float&#91;&#93;&#123; 26, 3f, 0.820f, -1000, -700, -100, 3.57f, 1.12f, 0.91f, -800, 0.059f, 0f, 0f, 0f, -100, 0.037f, 0f, 0f, 0f, 0.250f, 0.140f, 0.250f, 0f, -7f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;
CityAbandoned = new Environment &#40; new float&#91;&#93;&#123; 26, 3f, 0.690f, -1000, -200, -100, 3.28f, 1.17f, 0.91f, -700, 0.044f, 0f, 0f, 0f, -1100, 0.024f, 0f, 0f, 0f, 0.250f, 0.200f, 0.250f, 0f, -3f, 5000f, 250f, 0f, 0x20&#125; &#41; &#41;;</pre>
</div>
<h2><a>Small Indoor Rooms</a></h2>
<div>
<pre>Room = new Environment &#40; new float&#91;&#93;&#123; 2, 1.9f, 1f, -1000, -454, 0, 0.40f, 0.83f, 1f, -1646, 0.002f, 0f, 0f, 0f, 53, 0.003f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Bathroom = new Environment &#40; new float&#91;&#93;&#123; 3, 1.4f, 1f, -1000, -1200, 0, 1.49f, 0.54f, 1f, -370, 0.007f, 0f, 0f, 0f, 1030, 0.011f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Livingroom = new Environment &#40; new float&#91;&#93;&#123; 4, 2.5f, 1f, -1000, -6000, 0, 0.50f, 0.10f, 1f, -1376, 0.003f, 0f, 0f, 0f, -1104, 0.004f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Paddedcell = new Environment &#40; new float&#91;&#93;&#123; 1, 1.4f, 1f, -1000, -6000, 0, 0.17f, 0.10f, 1f, -1204, 0.001f, 0f, 0f, 0f, 207, 0.002f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Stoneroom = new Environment &#40; new float&#91;&#93;&#123; 5, 11.6f, 1f, -1000, -300, 0, 2.31f, 0.64f, 1f, -711, 0.012f, 0f, 0f, 0f, 83, 0.017f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Medium-Sized Indoor Rooms</a></h2>
<div>
<pre>Workshop = new Environment &#40; new float&#91;&#93;&#123; 26, 1.9f, 1f, -1000, -1700, -800, 0.76f, 1f, 1f, 0, 0.012f, 0f, 0f, 0f, 100, 0.012f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;
Schoolroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.86f, 0.690f, -1000, -400, -600, 0.98f, 0.45f, 0.18f, 300, 0.017f, 0f, 0f, 0f, 300, 0.015f, 0f, 0f, 0f, 0.095f, 0.140f, 0.250f, 0f, -5f, 7176.9f, 211.2f, 0f, 0x20&#125; &#41; &#41;;
Practiseroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.86f, 0.870f, -1000, -800, -600, 1.12f, 0.56f, 0.18f, 200, 0.010f, 0f, 0f, 0f, 300, 0.011f, 0f, 0f, 0f, 0.095f, 0.140f, 0.250f, 0f, -5f, 7176.9f, 211.2f, 0f, 0x20&#125; &#41; &#41;;
Outhouse = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.820f, -1000, -1900, -1600, 1.38f, 0.38f, 0.35f, -100, 0.024f, 0f, 0f, -0f, -400, 0.044f, 0f, 0f, 0f, 0.121f, 0.170f, 0.250f, 0f, -5f, 2854.4f, 107.5f, 0f, 0x0&#125; &#41; &#41;;
Caravan = new Environment &#40; new float&#91;&#93;&#123; 26, 8.3f, 1f, -1000, -2100, -1800, 0.43f, 1.50f, 1f, 0, 0.012f, 0f, 0f, 0f, 600, 0.012f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
Dustyroom = new Environment &#40; new float&#91;&#93;&#123; 26, 1.8f, 0.560f, -1000, -200, -300, 1.79f, 0.38f, 0.21f, -600, 0.002f, 0f, 0f, 0f, 200, 0.006f, 0f, 0f, 0f, 0.202f, 0.050f, 0.250f, 0f, -10f, 13046f, 163.3f, 0f, 0x20&#125; &#41; &#41;;
Chapel = new Environment &#40; new float&#91;&#93;&#123; 26, 19.6f, 0.840f, -1000, -500, 0, 4.62f, 0.64f, 1.23f, -700, 0.032f, 0f, 0f, 0f, -200, 0.049f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0.110f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Large Indoor Rooms</a></h2>
<div>
<pre>Auditorium = new Environment &#40; new float&#91;&#93;&#123; 6, 21.6f, 1f, -1000, -476, 0, 4.32f, 0.59f, 1f, -789, 0.020f, 0f, 0f, 0f, -289, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Concerthall = new Environment &#40; new float&#91;&#93;&#123; 7, 19.6f, 1f, -1000, -500, 0, 3.92f, 0.70f, 1f, -1230, 0.020f, 0f, 0f, 0f, -02, 0.029f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Cave = new Environment &#40; new float&#91;&#93;&#123; 8, 14.6f, 1f, -1000, 0, 0, 2.91f, 1.30f, 1f, -602, 0.015f, 0f, 0f, 0f, -302, 0.022f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
Arena = new Environment &#40; new float&#91;&#93;&#123; 9, 36.2f, 1f, -1000, -698, 0, 7.24f, 0.33f, 1f, -1166, 0.020f, 0f, 0f, 0f, 16, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Hangar = new Environment &#40; new float&#91;&#93;&#123; 10, 50.3f, 1f, -1000, -1000, 0, 10.05f, 0.23f, 1f, -602, 0.020f, 0f, 0f, 0f, 198, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
DomeTomb = new Environment &#40; new float&#91;&#93;&#123; 26, 51.8f, 0.790f, -1000, -900, -1300, 4.18f, 0.21f, 0.10f, -825, 0.030f, 0f, 0f, 0f, 450, 0.022f, 0f, 0f, 0f, 0.177f, 0.190f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x0&#125; &#41; &#41;;
DomeSaintPauls = new Environment &#40; new float&#91;&#93;&#123; 26, 50.3f, 0.870f, -1000, -900, -1300, 10.48f, 0.19f, 0.10f, -1500, 0.090f, 0f, 0f, 0f, 200, 0.042f, 0f, 0f, 0f, 0.250f, 0.120f, 0.250f, 0f, -5f, 2854.4f, 20f, 0f, 0x3f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Hallways, Alleys</a></h2>
<div>
<pre>Carpettedhallway = new Environment &#40; new float&#91;&#93;&#123; 11, 1.9f, 1f, -1000, -4000, 0, 0.30f, 0.10f, 1f, -1831, 0.002f, 0f, 0f, 0f, -1630, 0.030f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Hallway = new Environment &#40; new float&#91;&#93;&#123; 12, 1.8f, 1f, -1000, -300, 0, 1.49f, 0.59f, 1f, -1219, 0.007f, 0f, 0f, 0f, 441, 0.011f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Stonecorridor = new Environment &#40; new float&#91;&#93;&#123; 13, 13.5f, 1f, -1000, -237, 0, 2.70f, 0.79f, 1f, -1214, 0.013f, 0f, 0f, 0f, 395, 0.020f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Alley = new Environment &#40; new float&#91;&#93;&#123; 14, 7.5f, 0.300f, -1000, -270, 0, 1.49f, 0.86f, 1f, -1204, 0.007f, 0f, 0f, 0f, -4, 0.011f, 0f, 0f, 0f, 0.125f, 0.950f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Outdoors</a></h2>
<div>
<pre>Backyard = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.450f, -1000, -1200, -600, 1.12f, 0.34f, 0.46f, -700, 0.069f, 0f, 0f, -0f, -300, 0.023f, 0f, 0f, 0f, 0.218f, 0.340f, 0.250f, 0f, -5f, 4399.1f, 242.9f, 0f, 0x0&#125; &#41; &#41;;
Plain = new Environment &#40; new float&#91;&#93;&#123; 19, 42.5f, 0.210f, -1000, -2000, 0, 1.49f, 0.50f, 1f, -2466, 0.179f, 0f, 0f, 0f, -1926, 0.100f, 0f, 0f, 0f, 0.250f, 1f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Rollingplains = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0f, -1000, -3900, -400, 2.13f, 0.21f, 0.46f, -1500, 0.300f, 0f, 0f, -0f, -700, 0.019f, 0f, 0f, 0f, 0.250f, 1f, 0.250f, 0f, -5f, 4399.1f, 242.9f, 0f, 0x0&#125; &#41; &#41;;
Deepcanyon = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.740f, -1000, -1500, -400, 3.89f, 0.21f, 0.46f, -1000, 0.223f, 0f, 0f, -0f, -900, 0.019f, 0f, 0f, 0f, 0.250f, 1f, 0.250f, 0f, -5f, 4399.1f, 242.9f, 0f, 0x0&#125; &#41; &#41;;
Creek = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.350f, -1000, -1500, -600, 2.13f, 0.21f, 0.46f, -800, 0.115f, 0f, 0f, -0f, -1400, 0.031f, 0f, 0f, 0f, 0.218f, 0.340f, 0.250f, 0f, -5f, 4399.1f, 242.9f, 0f, 0x0&#125; &#41; &#41;;
Valley = new Environment &#40; new float&#91;&#93;&#123; 26, 80.3f, 0.280f, -1000, -3100, -1600, 2.88f, 0.26f, 0.35f, -1700, 0.263f, 0f, 0f, -0f, -800, 0.100f, 0f, 0f, 0f, 0.250f, 0.340f, 0.250f, 0f, -5f, 2854.4f, 107.5f, 0f, 0x0&#125; &#41; &#41;;
Forest = new Environment &#40; new float&#91;&#93;&#123; 15, 38f, 0.300f, -1000, -3300, 0, 1.49f, 0.54f, 1f, -2560, 0.162f, 0f, 0f, 0f, -229, 0.088f, 0f, 0f, 0f, 0.125f, 1f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Mountains = new Environment &#40; new float&#91;&#93;&#123; 17, 100f, 0.270f, -1000, -2500, 0, 1.49f, 0.21f, 1f, -2780, 0.300f, 0f, 0f, 0f, -1434, 0.100f, 0f, 0f, 0f, 0.250f, 1f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;
Quarry = new Environment &#40; new float&#91;&#93;&#123; 18, 17.5f, 1f, -1000, -1000, 0, 1.49f, 0.83f, 1f, -10000, 0.061f, 0f, 0f, 0f, 500, 0.025f, 0f, 0f, 0f, 0.125f, 0.700f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Parkinglot = new Environment &#40; new float&#91;&#93;&#123; 20, 8.3f, 1f, -1000, 0, 0, 1.65f, 1.50f, 1f, -1363, 0.008f, 0f, 0f, 0f, -1153, 0.012f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0f, -5f, 5000f, 250f, 0f, 0x1f&#125; &#41; &#41;;</pre>
</div>
<h2><a>Water</a></h2>
<div>
<pre>Underwater = new Environment &#40; new float&#91;&#93;&#123; 22, 1.8f, 1f, -1000, -4000, 0, 1.49f, 0.10f, 1f, -449, 0.007f, 0f, 0f, 0f, 1700, 0.011f, 0f, 0f, 0f, 0.250f, 0f, 1.180f, 0.348f, -5f, 5000f, 250f, 0f, 0x3f&#125; &#41; &#41;;
Smallwaterroom = new Environment &#40; new float&#91;&#93;&#123; 26, 36.2f, 0.700f, -1000, -698, 0, 1.51f, 1.25f, 1.14f, -100, 0.020f, 0f, 0f, 0f, 300, 0.030f, 0f, 0f, 0f, 0.179f, 0.150f, 0.895f, 0.190f, -7f, 5000f, 250f, 0f, 0x0&#125; &#41; &#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:audio_environment_presets?do=export_xhtmlbody">view online version</a></em></p>

@ -1,61 +1,96 @@
<h1><a
name="bloom_and_glow">Bloom and Glow</a></h1><div
class="level1"><p> Bloom is a popular shader effect in 3D games industry. It usually consist in displaying a glowing halo around light sources or bright areas of a scene.
In practice, the bright areas are extracted from the rendered scene, blurred and finally added up to the render.</p><p> Those images gives an idea of what bloom does. The left image has no bloom effect, the right image does. <br/> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nobloomsky.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nobloomsky.png" class="media" title="No bloom" alt="No bloom" /></a><a
href="/wiki/lib/exe/detail.php/jme3:advanced:blomsky.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/blomsky.png" class="media" title="Bloom" alt="Bloom" /></a></p></div><h1><a
name="bloom_usage">Bloom Usage</a></h1><div
class="level1"><ol><li
class="level1"><div
class="li"> Create a FilterPostProcessor</div></li><li
class="level1"><div
class="li"> Create a BloomFilter</div></li><li
class="level1"><div
class="li"> Add the filter to the processor</div></li><li
class="level1"><div
class="li"> Add the processor to the viewPort</div></li></ol><pre> FilterPostProcessor fpp=new FilterPostProcessor&#40;assetManager&#41;;
<h1><a>Bloom and Glow</a></h1>
<div>
<p>
Bloom is a popular shader effect in 3D games industry. It usually consist in displaying a glowing halo around light sources or bright areas of a scene.
In practice, the bright areas are extracted from the rendered scene, blurred and finally added up to the render.
</p>
<p>
Those images gives an idea of what bloom does. The left image has no bloom effect, the right image does. <br/>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nobloomsky.png"><img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/blomsky.png">
</p>
</div>
<h1><a>Bloom Usage</a></h1>
<div>
<ol>
<li><div> Create a FilterPostProcessor</div>
</li>
<li><div> Create a BloomFilter</div>
</li>
<li><div> Add the filter to the processor</div>
</li>
<li><div> Add the processor to the viewPort</div>
</li>
</ol>
<pre> FilterPostProcessor fpp=new FilterPostProcessor&#40;assetManager&#41;;
BloomFilter bloom=new BloomFilter&#40;&#41;;
fpp.addFilter&#40;bloom&#41;;
viewPort.addProcessor&#40;fpp&#41;;</pre><p> Here are the parameters that you can tweak :</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Parameter</th><th
class="col1 leftalign"> Method</th><th
class="col2"> Default</th><th
class="col3"> Description</th></tr><tr
class="row1"><td
class="col0 leftalign"> blur scale</td><td
class="col1"> <code>setBlurScale(float)</code></td><td
class="col2 leftalign">1.5f</td><td
class="col3"> the scale of the bloom effect, but be careful, high values does artifacts</td></tr><tr
class="row2"><td
class="col0 leftalign"> exposure Power</td><td
class="col1"> <code>setExposurePower(float)</code></td><td
class="col2 leftalign">5.0f</td><td
class="col3"> the glowing channel color is raised to the value power</td></tr><tr
class="row3"><td
class="col0 leftalign"> exposure cut-off</td><td
class="col1"> <code>setExposureCutOff(float)</code></td><td
class="col2 leftalign">0.0f</td><td
class="col3"> the threshold of color to bloom during extraction</td></tr><tr
class="row4"><td
class="col0 leftalign"> bloom intensity</td><td
class="col1"> <code>setBloomIntensity(float)</code></td><td
class="col2 leftalign">2.0f</td><td
class="col3"> the resulting bloom value is multiplied by this intensity</td></tr></table></div><p> You&#039;ll probably need to adjust those parameters depending on your scene.</p></div><h1><a
name="bloom_with_a_glow_map">Bloom with a glow map</a></h1><div
class="level1"><p> Sometimes, you want to have more control over what glows and does not glow.
The bloom filter supports a glow map or a glow color.</p></div><h5><a
name="creating_a_glow-map">Creating a glow-map</a></h5><div
class="level5"><p> Let&#039;s take the hover tank example bundled with JME3 test data.<br/> Here you can see the diffuse map of the tank, and the associated glow map that only contains the parts of the texture that will glow and their glowing color: <br/> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:tank_diffuse_ss.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tank_diffuse_ss.png" class="media" title="Tank diffuse map" alt="Tank diffuse map" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:tank_glow_map_ss.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tank_glow_map_ss.png" class="media" title="Tank glow map" alt="Tank glow map" /></a></p><p> Glow maps works with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions.
The tank material looks like that :</p><pre>Material My Material : Common/MatDefs/Light/Lighting.j3md {
viewPort.addProcessor&#40;fpp&#41;;</pre>
<p>
Here are the parameters that you can tweak :
</p>
<div><table>
<tr>
<th> Parameter </th><th> Method </th><th> Default </th><th> Description </th>
</tr>
<tr>
<td> blur scale </td><td> <code>setBlurScale(float)</code> </td><td>1.5f </td><td> the scale of the bloom effect, but be careful, high values does artifacts </td>
</tr>
<tr>
<td> exposure Power </td><td> <code>setExposurePower(float)</code> </td><td>5.0f </td><td> the glowing channel color is raised to the value power </td>
</tr>
<tr>
<td> exposure cut-off </td><td> <code>setExposureCutOff(float)</code> </td><td>0.0f </td><td> the threshold of color to bloom during extraction </td>
</tr>
<tr>
<td> bloom intensity </td><td> <code>setBloomIntensity(float)</code> </td><td>2.0f </td><td> the resulting bloom value is multiplied by this intensity </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [865-1454] -->
<p>
You&#039;ll probably need to adjust those parameters depending on your scene.
</p>
</div>
<h1><a>Bloom with a glow map</a></h1>
<div>
<p>
Sometimes, you want to have more control over what glows and does not glow.
The bloom filter supports a glow map or a glow color.
</p>
</div>
<h5><a>Creating a glow-map</a></h5>
<div>
<p>
Let&#039;s take the hover tank example bundled with JME3 test data.<br/>
Here you can see the diffuse map of the tank, and the associated glow map that only contains the parts of the texture that will glow and their glowing color: <br/>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tank_diffuse_ss.png">
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tank_glow_map_ss.png">
</p>
<p>
Glow maps works with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions.
The tank material looks like that :
</p>
<pre>Material My Material : Common/MatDefs/Light/Lighting.j3md {
MaterialParameters {
SpecularMap : Models/HoverTank/tank_specular.png
Shininess : 8
@ -67,77 +102,183 @@ The tank material looks like that :</p><pre>Material My Material : Common/MatDef
Diffuse : 1.0 1.0 1.0 1.0
Specular : 1.0 1.0 1.0 1.0
}
}</pre><p> The glow map is defined here : <strong>GlowMap : Models/HoverTank/tank_glow_map_highres.png</strong></p></div><h5><a
name="usage">Usage</a></h5><div
class="level5"><ol><li
class="level1"><div
class="li"> Create a FilterPostProcessor</div></li><li
class="level1"><div
class="li"> Create a BloomFilter with the GlowMode.Objects parameter</div></li><li
class="level1"><div
class="li"> Add the filter to the processor</div></li><li
class="level1"><div
class="li"> Add the processor to the viewPort</div></li></ol><pre> FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
}</pre>
<p>
The glow map is defined here : <strong>GlowMap : Models/HoverTank/tank_glow_map_highres.png</strong>
</p>
</div>
<h5><a>Usage</a></h5>
<div>
<ol>
<li><div> Create a FilterPostProcessor</div>
</li>
<li><div> Create a BloomFilter with the GlowMode.Objects parameter</div>
</li>
<li><div> Add the filter to the processor</div>
</li>
<li><div> Add the processor to the viewPort</div>
</li>
</ol>
<pre> FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
BloomFilter bf=new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bf);
viewPort.addProcessor(fpp);</pre><p> Here is the result : <br/> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:tanlglow1.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tanlglow1.png" class="media" title="Glowing hover tank" alt="Glowing hover tank" /></a></p></div><h1><a
name="bloom_with_a_glow_color">Bloom with a glow color</a></h1><div
class="level1"><p> Sometimes you need an entire object to glow, not just parts of it.
In this case you&#039;ll need to use the glow color parameter.</p></div><h5><a
name="usage1">Usage</a></h5><div
class="level5"><ol><li
class="level1"><div
class="li"> Create a material for your object and set the GlowColor parameter</div></li><li
class="level1"><div
class="li"> Create a FilterPostProcessor</div></li><li
class="level1"><div
class="li"> Create a BloomFilter with the GlowMode.Objects parameter</div></li><li
class="level1"><div
class="li"> Add the filter to the processor</div></li><li
class="level1"><div
class="li"> Add the processor to the viewPort</div></li></ol><pre> Material mat = new Material(getAssetManager(), &quot;Common/MatDefs/Misc/SolidColor.j3md&quot;);
viewPort.addProcessor(fpp);</pre>
<p>
Here is the result : <br/>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/tanlglow1.png">
</p>
</div>
<h1><a>Bloom with a glow color</a></h1>
<div>
<p>
Sometimes you need an entire object to glow, not just parts of it.
In this case you&#039;ll need to use the glow color parameter.
</p>
</div>
<h5><a>Usage</a></h5>
<div>
<ol>
<li><div> Create a material for your object and set the GlowColor parameter</div>
</li>
<li><div> Create a FilterPostProcessor</div>
</li>
<li><div> Create a BloomFilter with the GlowMode.Objects parameter</div>
</li>
<li><div> Add the filter to the processor</div>
</li>
<li><div> Add the processor to the viewPort</div>
</li>
</ol>
<pre> Material mat = new Material(getAssetManager(), &quot;Common/MatDefs/Misc/SolidColor.j3md&quot;);
mat.setColor(&quot;Color&quot;, ColorRGBA.Green);
mat.setColor(&quot;GlowColor&quot;, ColorRGBA.Green);
fpp=new FilterPostProcessor(assetManager);
bloom= new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);</pre><p> Here is the result on Oto&#039;s plasma ball (before and after) : <br/> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:otonobloom.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png?w=400" class="medialeft" align="left" title="Oto&#039;s plasma ball is just a big pea" alt="Oto&#039;s plasma ball is just a big pea" width="400" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:otoglow.png?id=jme3%3Aadvanced%3Abloom_and_glow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/otoglow.png?w=400" class="medialeft" align="left" title="Oto&#039;s plasma ball radiates incredible power!!!" alt="Oto&#039;s plasma ball radiates incredible power!!!" width="400" /></a></p></div><h1><a
name="hints_and_tricks">Hints and tricks</a></h1><div
class="level1"></div><h5><a
name="increasing_the_blur_range_and_reducing_fps_cost">Increasing the blur range and reducing fps cost</a></h5><div
class="level5"><p> The glow render is sampled on a texture that has the same dimensions as the viewport.
You can reduce the size of the bloom sampling just by using the setDownSamplingFactor method like this : <br/></p><pre> BloomFilter bloom=new BloomFilter&#40;&#41;;
bloom.setDownSamplingFactor&#40;2.0f&#41;; </pre><p> In this example the sampling size is divided by 4 (width/2,height/2), resulting in less work to blur the scene.
The resulting texture is then up sampled to the screen size using hardware bilinear filtering. this results in a wider blur range.</p></div><h5><a
name="using_classic_bloom_combined_with_a_glow_map">Using classic bloom combined with a glow map</a></h5><div
class="level5"><p> let&#039;s say you want a global bloom on your scene, but you have also a glowing object on it.
You can use only one bloom filter for both effects like that</p><pre>BloomFilter bloom=new BloomFilter&#40;BloomFilter.GlowMode.SceneAndObjects&#41;;</pre><p> However, note that both effects will share the same values of attribute, and sometimes, it won&#039;t be what you need.</p></div><h5><a
name="making_your_home_brewed_material_definition_support_glow">Making your home brewed material definition support Glow</a></h5><div
class="level5"><p> Let&#039;s say you have made a custom material on your own, and that you want it to support glow maps and glow color.
In your material definition you need to add those lines in the MaterialParameters section :</p><pre> MaterialParameters {
viewPort.addProcessor(fpp);</pre>
<p>
Here is the result on Oto&#039;s plasma ball (before and after) : <br/>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/otonobloom.png">
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/otoglow.png">
</p>
</div>
<h1><a>Hints and tricks</a></h1>
<div>
</div>
<h5><a>Increasing the blur range and reducing fps cost</a></h5>
<div>
<p>
The glow render is sampled on a texture that has the same dimensions as the viewport.
You can reduce the size of the bloom sampling just by using the setDownSamplingFactor method like this : <br/>
</p>
<pre> BloomFilter bloom=new BloomFilter&#40;&#41;;
bloom.setDownSamplingFactor&#40;2.0f&#41;; </pre>
<p>
In this example the sampling size is divided by 4 (width/2,height/2), resulting in less work to blur the scene.
The resulting texture is then up sampled to the screen size using hardware bilinear filtering. this results in a wider blur range.
</p>
</div>
<h5><a>Using classic bloom combined with a glow map</a></h5>
<div>
<p>
let&#039;s say you want a global bloom on your scene, but you have also a glowing object on it.
You can use only one bloom filter for both effects like that
</p>
<pre>BloomFilter bloom=new BloomFilter&#40;BloomFilter.GlowMode.SceneAndObjects&#41;;</pre>
<p>
However, note that both effects will share the same values of attribute, and sometimes, it won&#039;t be what you need.
</p>
</div>
<h5><a>Making your home brewed material definition support Glow</a></h5>
<div>
<p>
Let&#039;s say you have made a custom material on your own, and that you want it to support glow maps and glow color.
In your material definition you need to add those lines in the MaterialParameters section :
</p>
<pre> MaterialParameters {
....
// Texture of the glowing parts of the material
Texture2D GlowMap
// The glow color of the object
Color GlowColor
}</pre><p> Then add the following technique :</p><pre> Technique Glow {
}</pre>
<p>
Then add the following technique :
</p>
<pre> Technique Glow {
LightMode SinglePass
VertexShader GLSL100: Common/MatDefs/Misc/SimpleTextured.vert
FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag
WorldParameters {
WorldViewProjectionMatrix
}
Defines {
HAS_GLOWMAP : GlowMap
HAS_GLOWCOLOR : GlowColor
}
}</pre><p> Then you can use this material with the BloomFilter</p></div><h5><a
name="make_a_glowing_object_stop_to_glow">Make a glowing object stop to glow</a></h5><div
class="level5"><p> If you are using a glow map, remove the texture from the material.</p><pre>material.clearTextureParam(&quot;GlowMap&quot;);</pre><p> If you are using a glow color, set it to black</p><pre>material.setColor(&quot;GlowColor&quot;,ColorRGBA.Black);</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:bloom_and_glow?do=export_xhtmlbody">view online version</a></em></p>
}</pre>
<p>
Then you can use this material with the BloomFilter
</p>
</div>
<h5><a>Make a glowing object stop to glow</a></h5>
<div>
<p>
If you are using a glow map, remove the texture from the material.
</p>
<pre>material.clearTextureParam(&quot;GlowMap&quot;);</pre>
<p>
If you are using a glow color, set it to black
</p>
<pre>material.setColor(&quot;GlowColor&quot;,ColorRGBA.Black);</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:bloom_and_glow?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

@ -0,0 +1,43 @@
<h1><a>Multithreading Bullet Physics in jme3</a></h1>
<div>
</div>
<h2><a>Introduction</a></h2>
<div>
<p>
Since bullet is not (yet) multithreaded or GPU accelerated the jME3 implementation allows to run each physics space on a separate thread that is executed in parallel to rendering.
</p>
</div>
<h2><a>How is it handled in jme3 and bullet?</a></h2>
<div>
<p>
A SimpleApplication with a BulletAppState allows setting the threading type via
</p>
<pre>setThreadingType(ThreadingType type);</pre>
<p>
where ThreadingType can be either SEQUENTIAL or PARALLEL.
</p>
<p>
In the simpleInitApp() method:
</p>
<pre>bulletAppState = new BulletAppState&#40;&#41;;
bulletAppState.setThreadingType&#40;BulletAppState.ThreadingType.PARALLEL&#41;;
stateManager.attach&#40;bulletAppState&#41;;</pre>
<p>
The physics update happens in parallel to rendering, after the users changes have been made in the update() call. This way the loop logic is still maintained: the user can set and change values in physics and scenegraph objects before render() and physicsUpdate() are called in parallel. More physics spaces can simply be added by using multiple bulletAppStates.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:bullet_multithreading?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@ -1,132 +1,173 @@
<h1><a
name="the_jme3_camera">The jME3 Camera</a></h1><div
class="level1"></div><h2><a
name="default_camera">Default Camera</a></h2><div
class="level2"><p> The default com.jme3.renderer.Camera object is <code>cam</code> in com.jme3.app.Application.</p><p> The camera object is created with the following defaults:</p><ul><li
class="level1"><div
class="li"> Width and height are set to the current Application&#039;s settings.getWidth() and settings.getHeight() values.</div></li><li
class="level1"><div
class="li"> Frustum Perspective:</div><ul><li
class="level2"><div
class="li"> Frame of view angle of 45° along the Y axis</div></li><li
class="level2"><div
class="li"> Aspect ratio of width divided by height</div></li><li
class="level2"><div
class="li"> Near view plane of 1 wu</div></li><li
class="level2"><div
class="li"> Far view plane of 1000 wu</div></li></ul></li><li
class="level1"><div
class="li"> Start location at (0f, 0f, 10f).</div></li><li
class="level1"><div
class="li"> Start direction is looking at the origin.</div></li></ul><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">cam.getLocation(), setLocation()</td><td
class="col1">The camera position</td></tr><tr
class="row2"><td
class="col0">cam.getRotation(), setRotation()</td><td
class="col1">The camera rotation</td></tr><tr
class="row3"><td
class="col0">cam.getLeft(), setLeft()</td><td
class="col1">The left axis of the camera</td></tr><tr
class="row4"><td
class="col0">cam.getUp(), setUp()</td><td
class="col1">The up axis of the camera, usually Vector3f(0,1,0)</td></tr><tr
class="row5"><td
class="col0">cam.getDirection(), setDirection()</td><td
class="col1">The vector the camera is facing</td></tr><tr
class="row6"><td
class="col0">cam.getAxes(), setAxes(left,up,dir)</td><td
class="col1">One accessor for the three properties left/up/direction.</td></tr><tr
class="row7"><td
class="col0">cam.getFrame(), setFrame(loc,left,up,dir)</td><td
class="col1">One accessor for the four properties location/left/up/direction.</td></tr><tr
class="row8"><td
class="col0">cam.resize(width, height, fixAspect)</td><td
class="col1">Resize an existing camera object while keeping all other settings. Set fixAspect to true to adjust the aspect ratio (?)</td></tr><tr
class="row9"><td
class="col0">cam.setFrustum( near, far, left, right, top, bottom )</td><td
class="col1">The frustrum is defined by the near/far plane, left/rught plane, top/bottom plane (all distances as float values)</td></tr><tr
class="row10"><td
class="col0">cam.setFrustumPerspective( fovY, aspect ratio, near, far)</td><td
class="col1">The frustrum is defined by view angle along the Y axis (in degrees), aspect ratio, and the near/far plane.</td></tr><tr
class="row11"><td
class="col0">cam.lookAt(target,up)</td><td
class="col1">Turn the camera to look at Coordinate target, and rotate it around the up axis.</td></tr><tr
class="row12"><td
class="col0">cam.setParallelProjection(false)</td><td
class="col1">Normal perspective</td></tr><tr
class="row13"><td
class="col0">cam.setParallelProjection(true)</td><td
class="col1">Parallel projection perspective</td></tr><tr
class="row14"><td
class="col0">cam.getScreenCoordinates()</td><td
class="col1">?</td></tr></table></div><p> <strong>Tip:</strong> After you change view port, frustrum, or frame, call <code>cam.update();</code></p></div><h2><a
name="flyby_camera">FlyBy Camera</a></h2><div
class="level2"><p> The flyby camera is an extension of the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and for strafing to the sides. Move the mouse to rotate the camera, scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">flyCam.setEnabled(true);</td><td
class="col1">Activate the flyby cam</td></tr><tr
class="row2"><td
class="col0">flyCam.setMoveSpeed(10);</td><td
class="col1">Control the move speed</td></tr><tr
class="row3"><td
class="col0">flyCam.setRotationSpeed(10);</td><td
class="col1">Control the rotation speed</td></tr><tr
class="row4"><td
class="col0">flyCam.setDragToRotate(true)</td><td
class="col1">Must keep mouse button pressed to rotate camera. Used e.g. for Applets. if false, all mouse movement will be captured and interpreted as rotations.</td></tr></table></div></div><h2><a
name="chase_camera">Chase Camera</a></h2><div
class="level2"><p> jME3 also supports a Chase Cam that can follow a moving target Spatial (<code>com.jme3.input.ChaseCamera</code>). Click and hold the mouse button to rotate around the target.</p><pre>flyCam.setEnabled&#40;false&#41;;
ChaseCamera chaseCam = new ChaseCamera&#40;cam, target, inputManager&#41;;</pre><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0">Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">chaseCam.setSmoothMotion(true);</td><td
class="col1">Interpolates a smoother acceleration/deceleration when the camera moves.</td></tr><tr
class="row2"><td
class="col0">chaseCam.setChasingSensitivity(5f)</td><td
class="col1">The lower the chasing sensitivity, the slower the camera will follow the target when it moves.</td></tr><tr
class="row3"><td
class="col0">chaseCam.setTrailingSensitivity(0.5f)</td><td
class="col1">The lower the traling sensitivity, the slower the camera will begin to go after the target when it moves. Default is 0.5;</td></tr><tr
class="row4"><td
class="col0">chaseCam.setRotationSensitivity(5f)</td><td
class="col1">The lower the sensitivity, the slower the camera will rotate around the target when the mosue is dragged. Default is 5.</td></tr><tr
class="row5"><td
class="col0">chaseCam.setTrailingRotationInertia(0.1f)</td><td
class="col1">This prevents the camera to stop too abruptly when the target stops rotating before the camera has reached the target&#039;s trailing position. Default is 0.1f.</td></tr><tr
class="row6"><td
class="col0">chaseCam.setDefaultDistance(40);</td><td
class="col1">The default distance to the target at the start of the application.</td></tr><tr
class="row7"><td
class="col0">chaseCam.setMaxDistance(40);</td><td
class="col1">The maximum zoom distance. Default is 40f.</td></tr><tr
class="row8"><td
class="col0">chaseCam.setMinDistance(1);</td><td
class="col1">The minimum zoom distance. Default is 1f.</td></tr><tr
class="row9"><td
class="col0">chaseCam.setMinVerticalRotation(-FastMath.PI/2);</td><td
class="col1">The minimal vertical rotation angle of the camera around the target. Default is 0.</td></tr><tr
class="row10"><td
class="col0">chaseCam.setDefaultVerticalRotation(-FastMath.PI/2);</td><td
class="col1">The default vertical rotation angle of the camera around the target at the start of the application.</td></tr><tr
class="row11"><td
class="col0">chaseCam.setDefaultHorizontalRotation(-FastMath.PI/2);</td><td
class="col1">The default horizontal rotation angle of the camera around the target at the start of the application.</td></tr></table></div><div
class="tags"><span> <a
href="/wiki/doku.php/tag:camera?do=showtag&amp;tag=tag%3Acamera">camera</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:camera?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>The jME3 Camera</a></h1>
<div>
</div>
<h2><a>Default Camera</a></h2>
<div>
<p>
The default com.jme3.renderer.Camera object is <code>cam</code> in com.jme3.app.Application.
</p>
<p>
The camera object is created with the following defaults:
</p>
<ul>
<li><div> Width and height are set to the current Application&#039;s settings.getWidth() and settings.getHeight() values. </div>
</li>
<li><div> Frustum Perspective:</div>
<ul>
<li><div> Frame of view angle of 45° along the Y axis</div>
</li>
<li><div> Aspect ratio of width divided by height</div>
</li>
<li><div> Near view plane of 1 wu</div>
</li>
<li><div> Far view plane of 1000 wu</div>
</li>
</ul>
</li>
<li><div> Start location at (0f, 0f, 10f).</div>
</li>
<li><div> Start direction is looking at the origin.</div>
</li>
</ul>
<div><table>
<tr>
<th>Method</th><th>Usage</th>
</tr>
<tr>
<td>cam.getLocation(), setLocation()</td><td>The camera position</td>
</tr>
<tr>
<td>cam.getRotation(), setRotation()</td><td>The camera rotation</td>
</tr>
<tr>
<td>cam.getLeft(), setLeft()</td><td>The left axis of the camera</td>
</tr>
<tr>
<td>cam.getUp(), setUp()</td><td>The up axis of the camera, usually Vector3f(0,1,0)</td>
</tr>
<tr>
<td>cam.getDirection(), setDirection()</td><td>The vector the camera is facing</td>
</tr>
<tr>
<td>cam.getAxes(), setAxes(left,up,dir)</td><td>One accessor for the three properties left/up/direction.</td>
</tr>
<tr>
<td>cam.getFrame(), setFrame(loc,left,up,dir)</td><td>One accessor for the four properties location/left/up/direction.</td>
</tr>
<tr>
<td>cam.resize(width, height, fixAspect)</td><td>Resize an existing camera object while keeping all other settings. Set fixAspect to true to adjust the aspect ratio (?)</td>
</tr>
<tr>
<td>cam.setFrustum( near, far, left, right, top, bottom )</td><td>The frustrum is defined by the near/far plane, left/rught plane, top/bottom plane (all distances as float values)</td>
</tr>
<tr>
<td>cam.setFrustumPerspective( fovY, aspect ratio, near, far)</td><td>The frustrum is defined by view angle along the Y axis (in degrees), aspect ratio, and the near/far plane.</td>
</tr>
<tr>
<td>cam.lookAt(target,up)</td><td>Turn the camera to look at Coordinate target, and rotate it around the up axis.</td>
</tr>
<tr>
<td>cam.setParallelProjection(false)</td><td>Normal perspective</td>
</tr>
<tr>
<td>cam.setParallelProjection(true)</td><td>Parallel projection perspective</td>
</tr>
<tr>
<td>cam.getScreenCoordinates()</td><td>?</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [583-1860] -->
<p>
<strong>Tip:</strong> After you change view port, frustrum, or frame, call <code>cam.update();</code>
</p>
</div>
<h2><a>FlyBy Camera</a></h2>
<div>
<p>
The flyby camera is an extension of the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and for strafing to the sides. Move the mouse to rotate the camera, scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera.
</p>
<div><table>
<tr>
<th>Method</th><th>Usage</th>
</tr>
<tr>
<td>flyCam.setEnabled(true);</td><td>Activate the flyby cam</td>
</tr>
<tr>
<td>flyCam.setMoveSpeed(10);</td><td>Control the move speed</td>
</tr>
<tr>
<td>flyCam.setRotationSpeed(10);</td><td>Control the rotation speed</td>
</tr>
<tr>
<td>flyCam.setDragToRotate(true)</td><td>Must keep mouse button pressed to rotate camera. Used e.g. for Applets. if false, all mouse movement will be captured and interpreted as rotations.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [2298-2649] -->
</div>
<h2><a>Chase Camera</a></h2>
<div>
<p>
jME3 also supports a Chase Cam that can follow a moving target Spatial (<code>com.jme3.input.ChaseCamera</code>). Click and hold the mouse button to rotate around the target.
</p>
<pre>flyCam.setEnabled&#40;false&#41;;
ChaseCamera chaseCam = new ChaseCamera&#40;cam, target, inputManager&#41;;</pre>
<div><table>
<tr>
<th>Method</th><th>Usage</th>
</tr>
<tr>
<td>chaseCam.setSmoothMotion(true);</td><td>Interpolates a smoother acceleration/deceleration when the camera moves.</td>
</tr>
<tr>
<td>chaseCam.setChasingSensitivity(5f)</td><td>The lower the chasing sensitivity, the slower the camera will follow the target when it moves.</td>
</tr>
<tr>
<td>chaseCam.setTrailingSensitivity(0.5f)</td><td>The lower the traling sensitivity, the slower the camera will begin to go after the target when it moves. Default is 0.5;</td>
</tr>
<tr>
<td>chaseCam.setRotationSensitivity(5f)</td><td>The lower the sensitivity, the slower the camera will rotate around the target when the mosue is dragged. Default is 5.</td>
</tr>
<tr>
<td>chaseCam.setTrailingRotationInertia(0.1f)</td><td>This prevents the camera to stop too abruptly when the target stops rotating before the camera has reached the target&#039;s trailing position. Default is 0.1f.</td>
</tr>
<tr>
<td>chaseCam.setDefaultDistance(40);</td><td>The default distance to the target at the start of the application.</td>
</tr>
<tr>
<td>chaseCam.setMaxDistance(40);</td><td>The maximum zoom distance. Default is 40f.</td>
</tr>
<tr>
<td>chaseCam.setMinDistance(1);</td><td>The minimum zoom distance. Default is 1f.</td>
</tr>
<tr>
<td>chaseCam.setMinVerticalRotation(-FastMath.PI/2);</td><td>The minimal vertical rotation angle of the camera around the target. Default is 0.</td>
</tr>
<tr>
<td>chaseCam.setDefaultVerticalRotation(-FastMath.PI/2);</td><td>The default vertical rotation angle of the camera around the target at the start of the application.</td>
</tr>
<tr>
<td>chaseCam.setDefaultHorizontalRotation(-FastMath.PI/2);</td><td>The default horizontal rotation angle of the camera around the target at the start of the application.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [2958-4430] --><div><span>
<a href="/wiki/doku.php/tag:camera?do=showtag&amp;tag=tag%3Acamera">camera</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:camera?do=export_xhtmlbody">view online version</a></em></p>

@ -1,228 +1,438 @@
<h1><a
name="jme3_cinematics">jME3 Cinematics</a></h1><div
class="level1"><p> JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game. You use cinematics to script and record scenes. Use it for example to create <a
href="http://en.wikipedia.org/wiki/Cutscene">cutscenes</a> of your game.</p><p> Cinematics are implemented as AppStates. Attach the scene that you want to be visible in the cinematic to one Node. You create a Cinematic object, and add individual CinematicEvents to it.</p></div><h2><a
name="overview">Overview</a></h2><div
class="level2"><pre>Cinematic cinematic = new Cinematic&#40;sceneNode, duration&#41;;
cinematic.addCinematicEvent&#40;triggerTime, cinematicEvent&#41;;</pre><ol><li
class="level1"><div
class="li"> Create one Cinematic per scene.</div><ul><li
class="level2"><div
class="li"> sceneNode is the node containing the scene</div></li><li
class="level2"><div
class="li"> duration is the duration of the cinematic scene in seconds</div></li></ul></li><li
class="level1"><div
class="li"> Create CinematicEvents to script your &quot;movie&quot;. Each Cinematic is a set of CinematicEvents, that are triggered at a given time.</div><ul><li
class="level2"><div
class="li"> cinematicEvent is the cinematic event. More details below.</div></li><li
class="level2"><div
class="li"> triggerTime is the time when this particular cinematic event starts. Specify the start time in seconds since the beginning of the scene.</div></li></ul></li><li
class="level1"><div
class="li"> Play and pause the Cinematic using <code>cinematic.pause()</code> and <code>cinematic.play();</code></div></li></ol></div><h2><a
name="cinematicevents">CinematicEvents</a></h2><div
class="level2"><p> There are several kinds of cinematic events:</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">CinematicEvent</th><th
class="col1">Description</th></tr><tr
class="row1"><td
class="col0">MotionTrack</td><td
class="col1">Use this to move a Spatial non-linearly over time. A motionPath is a list of several waypoints added to a MotionPath. The path is interpolated using Catmull-Rom Splines between waypoints.</td></tr><tr
class="row2"><td
class="col0">PositionTrack</td><td
class="col1">Use this to move a Spatial linearly over time. It translates the Spatial to a destination in the given amount of time by linearly interpolating the positions.</td></tr><tr
class="row3"><td
class="col0">RotationTrack</td><td
class="col1">Use this to change the rotation of a Spatial over time. It rotates the Spatial in the given amount of time by linearly interpolating the rotation.</td></tr><tr
class="row4"><td
class="col0">ScaleTrack</td><td
class="col1">Use this to change the size of a Spatial over time. It scales the Spatial in the given amount of time by linearly interpolating the scale.</td></tr><tr
class="row5"><td
class="col0">SoundTrack</td><td
class="col1">Use this to play a sound at a given time for the given duration.</td></tr><tr
class="row6"><td
class="col0">GuiTrack</td><td
class="col1">Displays a <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <acronym
title="Graphical User Interface">GUI</acronym> <acronym
title="Extensible Markup Language">XML</acronym> to the cinematic using <code>cinematic.bindUi(&quot;path/to/nifty/file.xml&quot;);</code></td></tr><tr
class="row7"><td
class="col0">AnimationTrack</td><td
class="col1">Use this to start playing a model animation at a given time (a character walking animation for example)</td></tr></table></div><p> We will add more types of track implementions over time.</p><p> Each CinematicEvent supports the following methods to control the event.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">CinematicEvent method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">play()</td><td
class="col1">Starts playing the cinematic.</td></tr><tr
class="row2"><td
class="col0">stop()</td><td
class="col1">Stops playing the cinematic.</td></tr><tr
class="row3"><td
class="col0">pause()</td><td
class="col1">Pauses the cinematic.</td></tr></table></div><p> Those methods, must be called on the Cinematic and are propagated to the events. Don&#039;t use them directly on a sub cinematic event</p></div><h3><a
name="motiontrack_motionpath">MotionTrack &amp; MotionPath</a></h3><div
class="level3"><p> A motion track is made up of MotionPaths.</p><pre>MotionPath path = new MotionPath&#40;&#41;;</pre><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0"> MotionPath Method</th><th
class="col1"> Usage</th></tr><tr
class="row1"><td
class="col0">setCycle(true)</td><td
class="col1">Sets whether the motion along this path should be closed (true) or not (false).</td></tr><tr
class="row2"><td
class="col0">addWayPoint(vector)</td><td
class="col1">Adds individual waypoints to this path. The order is relevant.</td></tr><tr
class="row3"><td
class="col0">removeWayPoint(vector) <br/> removeWayPoint(index)</td><td
class="col1">Removes individual waypoints from this path. You can specify a vector or the integer index.</td></tr><tr
class="row4"><td
class="col0">setCurveTension(0.83f)</td><td
class="col1">Sets the tension of the curve (only for Catmull Rom Spline). A value of 0.0f will give a straight linear line, 1.0 a round curve.</td></tr><tr
class="row5"><td
class="col0">enableDebugShape(assetManager,rootNode)</td><td
class="col1">Shows a line to visualize the path. Used for debugging.</td></tr><tr
class="row6"><td
class="col0">disableDebugShape()</td><td
class="col1">Hides the line that visualizes the path. Used for debugging.</td></tr><tr
class="row7"><td
class="col0">getNbWayPoints()</td><td
class="col1">Returns the number of waypoints in this path.</td></tr></table></div><pre>MotionTrack thingMotionControl = new MotionTrack&#40;thingNode, path&#41;;</pre><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0">MotionTrack method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">setLoopMode(LoopMode.Loop)</td><td
class="col1">Sets whether the animation along this path should loop (true) or play only once (false).</td></tr><tr
class="row2"><td
class="col0">setDirectionType(MotionTrack.Direction.None)</td><td
class="col1">Sets the direction behavior type of the controled node. Direction.None deactivates this feature. See the following options:</td></tr><tr
class="row3"><td
class="col0">setDirectionType(MotionTrack.Direction.LookAt)</td><td
class="col1">Rotate to keep facing a point. Specify the point with setLookAt().</td></tr><tr
class="row4"><td
class="col0">setDirectionType(MotionTrack.Direction.Path)</td><td
class="col1">Face the direction of the path.</td></tr><tr
class="row5"><td
class="col0">setDirectionType(MotionTrack.Direction.PathAndRotation)</td><td
class="col1">Face the direction of the path, plus an added rotation. Use together with the setRotation() method.</td></tr><tr
class="row6"><td
class="col0">setDirectionType(MotionTrack.Direction.Rotation)</td><td
class="col1">Rotate while moving. Use together with the setRotation() method.</td></tr><tr
class="row7"><td
class="col0">setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)</td><td
class="col1">Optional: Make the moving face towards a certain location. Use together with setDirectionType().</td></tr><tr
class="row8"><td
class="col0">setRotation(quaternion)</td><td
class="col1">Optional: Sets the rotation. Use together with MotionTrack.Direction.Rotation or MotionTrack.Direction.PathAndRotation.</td></tr></table></div></div><h3><a
name="motionpathlistener">MotionPathListener</a></h3><div
class="level3"><p> You can register a MotionPathListener to the MotionPath to track whether waypoints have been reached, and then trigger a custom action. In this example we just print the status. The onWayPointReach() method of the interface gives you access to the MotionTrack object <code>control</code>, and an integer value representing the current wayPointIndex.</p><pre>path.addListener&#40; new MotionPathListener&#40;&#41; &#123;
public void onWayPointReach&#40;MotionTrack control, int wayPointIndex&#41; &#123;
if &#40;path.getNbWayPoints&#40;&#41; == wayPointIndex + 1&#41; &#123;
println&#40;control.getSpatial&#40;&#41;.getName&#40;&#41; + &quot;Finished!!! &quot;&#41;;
&#125; else &#123;
println&#40;control.getSpatial&#40;&#41;.getName&#40;&#41; + &quot; Reached way point &quot; + wayPointIndex&#41;;
<h1><a>JME3 Cinematics</a></h1>
<div>
<p>
JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. Combined with screen recording software, you use cinematics to create <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/Cutscene"><param name="text" value="<html><u>cutscenes</u></html>"><param name="textColor" value="blue"></object> and movies/trailers of your game. Internally, Cinematics are implemented as <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">AppStates</a>.
</p>
<p>
Short overview of the cinematic process:
</p>
<ol>
<li><div> Plan the script of your movie. <br/>
Write down a timeline (e.g. on paper) of which character should be at which spot at which time.</div>
</li>
<li><div> Attach the scene objects that you want to remote-control to one Node. <br/>
This Node can be the rootNode, or a Node that is attached to the rootNode. </div>
</li>
<li><div> Create a Cinematic object for this movie scene. The Cinematic will contain and manage the movie script.</div>
</li>
<li><div> For each line in your script (for each frame in your timeline), add a CinematicEvent to the Cinematic. </div>
</li>
</ol>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><param name="text" value="<html><u>TestCinematic.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>How to Use a Cinematic</a></h2>
<div>
<p>
A Cinematic is like a movie script for a node.
</p>
<pre>Cinematic cinematic = new Cinematic&#40;sceneNode, duration&#41;;
cinematic.addCinematicEvent&#40;starttime1, track1&#41;;
cinematic.addCinematicEvent&#40;starttime2, track2&#41;;
cinematic.addCinematicEvent&#40;starttime2, track3&#41;;
...
stateManager.attach&#40;cinematic&#41;;</pre>
<ol>
<li><div> Create one Cinematic per scripted scene.</div>
<ul>
<li><div> <code>sceneNode</code> is the node containing the scene (can be the rootNode).</div>
</li>
<li><div> <code>duration</code> is the duration of the whole scene in seconds.</div>
</li>
<li><div> Each Cinematic is a set of CinematicEvents, that are triggered at a given moment on the timeline.</div>
</li>
</ul>
</li>
<li><div> Create one CinematicEvent for each line of your movie script. </div>
<ul>
<li><div> <code>track</code> is one motion of a moving object. You can add several tracks. More details below.</div>
</li>
<li><div> <code>starttime</code> is the time when this particular cinematic event starts on the timeline. Specify the start time in seconds since the beginning of the cinematic.</div>
</li>
</ul>
</li>
<li><div> Attach the Cinematic to the SimpleApplication&#039;s stateManager. </div>
</li>
<li><div> Play, stop and pause the Cinematic from your code.</div>
</li>
</ol>
<div><table>
<tr>
<th>Method</th><th>Usage</th>
</tr>
<tr>
<td>cinematic.play()</td><td>Starts playing the cinematic from the start, or from where it was paused.</td>
</tr>
<tr>
<td>cinematic.stop()</td><td>Stops playing the cinematic and rewinds it.</td>
</tr>
<tr>
<td>cinematic.pause()</td><td>Pauses the cinematic.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [2215-2427] -->
</div>
<h2><a>Tracks (CinematicEvents)</a></h2>
<div>
<p>
Just like a movie script consists of lines with instructions to the actors, each Cinematic consists of a series of tracks.
</p>
<p>
Here is the list of available CinematicEvents that you use as tracks. Each track remote-controls scene objects in a different way:
</p>
<div><table>
<tr>
<th>Tracks (CinematicEvents)</th><th>Description</th>
</tr>
<tr>
<td>MotionTrack</td><td>Use a MotionTrack to move a Spatial non-linearly over time. A MotionTrack is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases. </td>
</tr>
<tr>
<td>PositionTrack</td><td>Use a PositionTrack to move a Spatial linearly over time. This linear interpolation results in straight motion segments between the way points. Use this to make the remote-controlled objects zig-zag from one way point to the other in a straight line.</td>
</tr>
<tr>
<td>RotationTrack</td><td>Use a RotationTrack to change the rotation of a Spatial over time. It spins the Spatial to the given angle in the given amount of time by linearly interpolating the rotation.</td>
</tr>
<tr>
<td>ScaleTrack</td><td>Use a ScaleTrack to change the size of a Spatial over time. It resizes the Spatial in the given amount of time by linearly interpolating the scale.</td>
</tr>
<tr>
<td>SoundTrack</td><td>Use a SoundTrack to play a <a href="/com/jme3/gde/core/docs/jme3/advanced/audio.html">sound</a> at a given time for the given duration.</td>
</tr>
<tr>
<td>GuiTrack</td><td>Displays a <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <acronym title="Graphical User Interface">GUI</acronym> <acronym title="Extensible Markup Language">XML</acronym> to the cinematic using <code>cinematic.bindUi(&quot;path/to/nifty/file.xml&quot;);</code></td>
</tr>
<tr>
<td>AnimationTrack</td><td>Use this to start playing a model <a href="/com/jme3/gde/core/docs/jme3/advanced/animation.html">animation</a> at a given time (a character walking animation for example)</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [2723-4144] -->
<p>
The jMonkey team can add more types of tracks, just ask in the forum.
</p>
</div>
<h3><a>MotionTrack</a></h3>
<div>
<p>
A MotionTrack moves a Spatial along a complex path.
</p>
<pre>MotionTrack track = new MotionTrack&#40;thingNode, path&#41;;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>thingNode</code> is the Spatial to be moved.</div>
</li>
<li><div> <code>path</code> is a complex <a href="/com/jme3/gde/core/docs/jme3/advanced/motionpath.html">MotionPath</a>.</div>
</li>
</ul>
<p>
To create a MotionTrack, do the following:
</p>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/motionpath.html">Create a MotionPath</a></div>
</li>
<li><div> Create a MotionTrack based on the MotionPath.</div>
</li>
<li><div> Configure your MotionTrack (see below).</div>
</li>
<li><div> Add the MotionTrack to a Cinematic.</div>
</li>
</ol>
<div><table>
<tr>
<th>MotionTrack configuration method</th><th>Usage</th>
</tr>
<tr>
<td>track.setLoopMode(LoopMode.Loop)</td><td>Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.None)</td><td>Sets the direction behavior type of the controled node. Direction.None deactivates this feature. You can choose from the following options: LookAt, Path, PathAndRotation, Rotation.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.LookAt)</td><td>The spatial turns (rotates) to keep facing a certain point while moving. Specify the point with the <code>setLookAt()</code> method.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.Path)</td><td>The spatial always faces in the direction of the path while moving.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.PathAndRotation)</td><td>The spatial faces the direction of the path, plus an added rotation. Use together with the <code>setRotation()</code> method.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.Rotation)</td><td>The spatial spins (rotates) while moving. You describe the spin by a custom quaternion. Use together with the <code>setRotation()</code> method.</td>
</tr>
<tr>
<td>track.setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)</td><td>The spatial always faces towards this location. Use together with <code>MotionTrack.Direction.LookAt</code>.</td>
</tr>
<tr>
<td>track.setRotation(quaternion)</td><td>Sets the rotation. Use together with <code>MotionTrack.Direction.Rotation</code> or <code>MotionTrack.Direction.PathAndRotation</code>.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [4701-6109] -->
<p>
<strong>Tip:</strong> Most likely you remote-control more than one object in your scene. Give the tracks and paths useful names such as <code>dragon_track</code>, <code>dragon_path</code>, <code>hero_track</code>, <code>hero_path</code>, etc.
</p>
</div>
<h3><a>PositionTrack</a></h3>
<div>
<p>
A PositionTrack moves a Spatial in a straight line from its current position to the end position.
</p>
<pre>PositionTrack track = new PositionTrack&#40;
thingNode, endPosition, duration, loopMode&#41;;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>thingNode</code> is the Spatial to be moved.</div>
</li>
<li><div> <code>endPosition</code> is the target location as Vector3f. </div>
</li>
<li><div> <code>duration</code> is the time that it should take from start to end point.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
<p>
The start location is always the current location of the Spatial.
</p>
</div>
<h3><a>RotationTrack</a></h3>
<div>
<p>
A RotationTrack remote-controls the rotation of a spatial.
</p>
<pre>RotationTrack thingRotationControl = new RotationTrack&#40;
thingNode, endRotation, duration, loopMode&#41;;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>thingNode</code> is the Spatial to be rotated.</div>
</li>
<li><div> <code>endRotation</code> is the target rotation in Quaternion format. </div>
</li>
<li><div> <code>duration</code> is the time that it should take from start to target rotation.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
</div>
<h3><a>ScaleTrack</a></h3>
<div>
<p>
A ScaleTrack remote-controls whether a spatial grows or shrinks.
</p>
<pre>ScaleTrack thingScaleControl = new ScaleTrack&#40;
thingNode, endScale, duration, loopMode&#41;;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>thingNode</code> is the Spatial to be resized.</div>
</li>
<li><div> <code>endScale</code> is the target Scale in Vector3f format. </div>
</li>
<li><div> <code>duration</code> is the time that it should take from start to target scale.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
</div>
<h3><a>SoundTrack</a></h3>
<div>
<p>
A SoundTrack plays a sound as part of the cinematic.
</p>
<pre>SoundTrack&#40; audioPath, isStream, duration, loopMode &#41;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>audioPath</code> is the path to an audio file as String, e.g. &quot;Sounds/mySound.wav&quot;.</div>
</li>
<li><div> <code>isStream</code> toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.</div>
</li>
<li><div> <code>duration</code> is the time that it should take to play.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
</div>
<h3><a>GuiTrack</a></h3>
<div>
<p>
A GuiTrack shows or hide a NiftyGUI as part of a cinematic.
</p>
<pre>GuiTrack&#40; screen, duration, loopMode &#41;</pre>
<p>
You must use this together with bindUI() to specify the Nifty <acronym title="Graphical User Interface">GUI</acronym> <acronym title="Extensible Markup Language">XML</acronym> file that you want to load:
</p>
<pre>cinematic.bindUi&#40;&quot;Interface/subtitle.xml&quot;&#41;;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>screen</code> is the name of the Nifty <acronym title="Graphical User Interface">GUI</acronym> screen to load, as String. </div>
</li>
<li><div> <code>duration</code> is the time that it should take to play.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
</div>
<h3><a>AnimationTrack</a></h3>
<div>
<p>
An AnimationTrack triggers an animation as part of a cinematic.
</p>
<pre>AnimationTrack&#40; thingNode, animationName, duration, loopMode &#41;</pre>
<p>
Details of the constructor:
</p>
<ul>
<li><div> <code>thingNode</code> is the Spatial whose animation you want to play.</div>
</li>
<li><div> <code>animationName</code> the name of the animation stored in the animated model that you want to trigger, as a String.</div>
</li>
<li><div> <code>duration</code> is the time that it should take to play.</div>
</li>
<li><div> <code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
</div>
<h3><a>Customizations</a></h3>
<div>
<p>
You can extend individual CinematicEvents. The <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/SubtitleTrack.java"><param name="text" value="<html><u>SubtitleTrack.java example</u></html>"><param name="textColor" value="blue"></object> shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><param name="text" value="<html><u>TestCinematic.java example</u></html>"><param name="textColor" value="blue"></object>.
</p>
<p>
You can also create new CinematicEvent by extending <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java"><param name="text" value="<html><u>AbstractCinematicEvent</u></html>"><param name="textColor" value="blue"></object>. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc… management. Look at the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><param name="text" value="<html><u>TestCinematic.java example</u></html>"><param name="textColor" value="blue"></object> is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.
</p>
</div>
<h2><a>Interacting with Cinematics</a></h2>
<div>
</div>
<h3><a>CinematicEventListener</a></h3>
<div>
<pre>CinematicEventListener cel = new CinematicEventListener&#40;&#41; &#123;
public void onPlay&#40;CinematicEvent cinematic&#41; &#123;
chaseCam.setEnabled&#40;false&#41;;
System.out.println&#40;&quot;play&quot;&#41;;
&#125;
&#125;
&#125;&#41;;</pre></div><h3><a
name="positiontrack">PositionTrack</a></h3><div
class="level3"><pre>PositionTrack thingPositionControl = new PositionTrack&#40;
thingNode, endPosition, duration, loopMode&#41;;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> thingNode is the Spatial to be moved.</div></li><li
class="level1"><div
class="li"> endPosition is the target location as Vector3f.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take from start to end point.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul><p> The start location is always the current location of the Spatial.</p></div><h3><a
name="rotationtrack">RotationTrack</a></h3><div
class="level3"><pre>RotationTrack thingRotationControl = new RotationTrack&#40;
thingNode, endRotation, duration, loopMode&#41;;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> thingNode is the Spatial to be rotated.</div></li><li
class="level1"><div
class="li"> endRotation is the target rotation in Quaternion format.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take from start to target rotation.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul></div><h3><a
name="scaletrack">ScaleTrack</a></h3><div
class="level3"><pre>ScaleTrack thingScaleControl = new ScaleTrack&#40;
thingNode, endScale, duration, loopMode&#41;;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> thingNode is the Spatial to be resized.</div></li><li
class="level1"><div
class="li"> endScale is the target Scale in Vector3f format.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take from start to target scale.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul></div><h3><a
name="soundtrack">SoundTrack</a></h3><div
class="level3"><pre>SoundTrack&#40; audioPath, isStream, duration, loopMode &#41;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> audioPath is the path to an audio file as String, e.g. &quot;Sounds/mySound.wav&quot;.</div></li><li
class="level1"><div
class="li"> isStream Set this to true to play a longer audio file as stream, or to false to play a short sound without streaming.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take to play.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul></div><h3><a
name="guitrack">GuiTrack</a></h3><div
class="level3"><pre>GuiTrack&#40; screen, duration, loopMode &#41;</pre><p> You must use this together with bindUI() to specify the Nifty <acronym
title="Graphical User Interface">GUI</acronym> <acronym
title="Extensible Markup Language">XML</acronym> file that you want to load:</p><pre>cinematic.bindUi&#40;&quot;Interface/subtitle.xml&quot;&#41;;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> screen is the name of the Nifty <acronym
title="Graphical User Interface">GUI</acronym> screen to load, as String.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take to play.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul></div><h3><a
name="animationtrack">AnimationTrack</a></h3><div
class="level3"><pre>AnimationTrack&#40; thingNode, animationName, duration, loopMode &#41;</pre><p> Details of the constructor:</p><ul><li
class="level1"><div
class="li"> thingNode is the Spatial whose animation you want to play.</div></li><li
class="level1"><div
class="li"> AnimationName the animation of the animated model that you want to trigger, as a String.</div></li><li
class="level1"><div
class="li"> duration is the time that it should take to play.</div></li><li
class="level1"><div
class="li"> loopMode can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div></li></ul></div><h3><a
name="customizations">Customizations</a></h3><div
class="level3"><p> You can extend individual CinematicEvents. The <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/SubtitleTrack.java">SubtitleTrack.java example</a> shows how to extend a GuiTrack to script subtitles. See how the subtitles are used in the <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java">TestCinematic.java example</a>.</p><p> You can also create new CinematicEvent by extending <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/cinematic/events/AbstractCinematicEvent.java">AbstractCinematicEvent</a>. An AbstractCinematicEvent implements the CinematicEvent interface and provides duration, time, speed, etc… management. Look at the <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java">TestCinematic.java example</a> is to use this for a custom fadeIn/fadeOut effect in combination with a com.jme3.post.filters.FadeFilter.</p></div><h2><a
name="camera_handling">Camera Handling</a></h2><div
class="level2"><p> The camera management is handled as follows:</p><ol><li
class="level1"><div
class="li"> Create a camera Node and bind the camera object to the cinematic. Note that we also give the camera node a name in this step.<pre>CameraNode camNode = cinematic.bindCamera&#40;&quot;topView&quot;, cam&#41;;</pre></div></li><li
class="level1"><div
class="li"> Position the camera node in its start location.</div></li><li
class="level1"><div
class="li"> Use activateCamera() to give the control of the camera to this node. You now see the scene from this camera&#039;s point of view. For example to see through the camera node named &quot;top view&quot;, 6 seconds after the start of the cinematic, you&#039;d write<pre>cinematic.activateCamera&#40;6, &quot;topView&quot;&#41;;</pre></div></li><li
class="level1"><div
class="li"> If desired, attach the camNode to a MotionTrack to let it travel along waypoints. This is demonstrated in the <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java">TestCameraMotionPath.java example</a>.</div></li></ol><p> Code samples:</p><pre>flyCam.setEnabled&#40;false&#41;;
&nbsp;
CameraNode camNodeTop = cinematic.bindCamera&#40;&quot;topView&quot;, cam&#41;;
camNodeTop.setControlDir&#40;ControlDirection.SpatialToCamera&#41;;
camNodeTop.getControl&#40;0&#41;.setEnabled&#40;false&#41;;
public void onPause&#40;CinematicEvent cinematic&#41; &#123;
chaseCam.setEnabled&#40;true&#41;;
System.out.println&#40;&quot;pause&quot;&#41;;
&#125;
&nbsp;
CameraNode camNodeSide = cinematic.bindCamera&#40;&quot;sideView&quot;, cam&#41;;
camNodeSide.setControlDir&#40;ControlDirection.CameraToSpatial&#41;;
camNodeSide.getControl&#40;0&#41;.setEnabled&#40;false&#41;;</pre></div><h2><a
name="physics_interaction">Physics Interaction</a></h2><div
class="level2"><p> Upcoming.</p></div><h2><a
name="more_information">More Information</a></h2><div
class="level2"><p> See also: <a
href="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/cinematics-system-for-jme3/">Cinematics by Nehon</a></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:cinematics?do=export_xhtmlbody">view online version</a></em></p>
public void onStop&#40;CinematicEvent cinematic&#41; &#123;
chaseCam.setEnabled&#40;true&#41;;
System.out.println&#40;&quot;stop&quot;&#41;;
&#125;
&#125;
cinematic.addListener&#40;cel&#41;;</pre>
</div>
<h3><a>Physics Interaction</a></h3>
<div>
<p>
Upcoming.
</p>
</div>
<h2><a>More Information</a></h2>
<div>
<p>
See also: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/cinematics-system-for-jme3/"><param name="text" value="<html><u>Cinematics by Nehon</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:cinematics?do=export_xhtmlbody">view online version</a></em></p>

@ -1,68 +1,127 @@
<h1><a
name="collision_and_intersection">Collision and Intersection</a></h1><div
class="level1"><p> The term collision can be used to refer to physical interactions (where physical objects collide and bump off one another), and also to non-physical intersections. This article is about non-physical (mathematical) collisions.
Non-physical collisions are interesting because they take less resources than physical ones. You cn optimize your game if you find a way to simulate a certain effect in a non-physical way, using mathematical techniques such as ray casting.
One example for an optimization is a physical vehicle&#039;s wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force – sounds very accurate, but is total overkill. An more performant solution is to cast four rays down from the vehicle and calculate the intersections with the floor and other obstacles. These non-physical wheels require (in the simplest case) only four calculations to achieve an effect that players can hardly distinguish from the real thing.</p></div><h2><a
name="bounding_volumes">Bounding Volumes</a></h2><div
class="level2"><p> A com.jme3.bounding.BoundingVolume is an interface for dealing with containment of a collection of points. All BoundingVolumes are Collidable and are used as optimization to calculate non-physical collisions more quickly: It&#039;s faster to calculate an intersection between simple shapes like spheres and boxes than between complex shapes. In cases where precision is not relevant, you wrap a complex model in a simpler shape to improve collision detection performance.</p><ul><li
class="level1"><div
class="li"> Type.Sphere: com.jme3.bounding.BoundingSphere is a sphere used as a container for a group of vertices of a piece of geometry. A BoundingSphere has a center and a radius.</div></li><li
class="level1"><div
class="li"> Type.AABB = Axis-aligned bounding box. A com.jme3.bounding.BoundingBox is an axis-aligned cuboid used as a container for a group of vertices of a piece of geometry. A BoundingBox has a center and extents from that center along the x, y and z axis.</div></li><li
class="level1"><div
class="li"> Type.OBB = Oriented bounding box. (not in use)</div></li><li
class="level1"><div
class="li"> Type.Capsule</div></li></ul><p> Note: Physical objects have their own &quot;bounding volumes&quot; called CollisionShapes.</p></div><h2><a
name="collisions">Collisions</a></h2><div
class="level2"><p> The interface com.jme3.collision.Collidable declares one method that returns how many collisions were found between two Collidables: <code>collideWith(Collidable other, CollisionResults results)</code>.
A <code>com.jme3.collision.CollisionResults</code> object is an ArrayList of comparable <code>com.jme3.collision.CollisionResult</code> objects.
You can iterate over the CollisionResults to identify the other parties involved in the collision. Note that jME counts <em>all</em> collisions, this means a ray intersecting a box will be counted as two hits, one on the front where the ray enters, and one on the back where the ray exits.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">CollisionResults Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0 leftalign">size()</td><td
class="col1">Returns the number of CollisionResult objects.</td></tr><tr
class="row2"><td
class="col0">getClosestCollision()</td><td
class="col1">Returns the CollisionResult with the lowest distance.</td></tr><tr
class="row3"><td
class="col0">getFarthestCollision()</td><td
class="col1">Returns the CollisionResult with the farthest distance.</td></tr><tr
class="row4"><td
class="col0 leftalign">getCollision(i)</td><td
class="col1">Returns the CollisionResult at index i.</td></tr></table></div><p> A CollisionResult object contains information about the second party of the collision event.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">CollisionResult Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">getContactPoint()</td><td
class="col1">Returns the contact point coordinate on the second party, as Vector3f.</td></tr><tr
class="row2"><td
class="col0">getContactNormal()</td><td
class="col1">Returns the Normal vector at the contact point, as Vector3f.</td></tr><tr
class="row3"><td
class="col0">getDistance()</td><td
class="col1">Returns the distance between the Collidable and the second party, as float.</td></tr><tr
class="row4"><td
class="col0">getGeometry()</td><td
class="col1">Returns the Geometry of the second party.</td></tr><tr
class="row5"><td
class="col0">getTriangle(t)</td><td
class="col1">Binds t to the triangle t on the second party&#039;s mesh that was hit.</td></tr><tr
class="row6"><td
class="col0">getTriangleIndex()</td><td
class="col1">Returns the index of the triangle on the second party&#039;s mesh that was hit. (?)</td></tr></table></div><p> Assume you have two collidables a and b and want to detect collisions between them. The collision parties can be Geometries, Nodes with Geometries attached (including the rootNode), Planes, Quads, Lines, or Rays. <br/> The following code snippet can be triggered by listeners (e.g. after an input action such as a click), or timed in the update loop.</p><pre> // Calculate Results
<h1><a>Collision and Intersection</a></h1>
<div>
<p>
The term collision can be used to refer to physical interactions (where physical objects collide and bump off one another), and also to non-physical intersections. This article is about non-physical (mathematical) collisions.
</p>
<p>
Non-physical collision detection is interesting because they use less computing resources than physical collision detection. You can optimize your game if you find a way to simulate a certain effect in a non-physical way, using mathematical techniques such as ray casting.
</p>
<p>
One example for an optimization is a physical vehicle&#039;s wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force – sounds very accurate, but is total overkill. A more performant solution is to cast four invisible rays down from the vehicle and calculate the intersections with the floor and other obstacles. These non-physical wheels require (in the simplest case) only four calculations to achieve an effect that players can hardly distinguish from the real thing.
</p>
</div>
<h2><a>Bounding Volumes</a></h2>
<div>
<p>
A com.jme3.bounding.BoundingVolume is an interface for dealing with containment of a collection of points. All BoundingVolumes are Collidable and are used as optimization to calculate non-physical collisions more quickly: It&#039;s faster to calculate an intersection between simple shapes like spheres and boxes than between complex shapes. In cases where precision is not relevant, you wrap a complex model in a simpler shape to speed up collision detection.
</p>
<ul>
<li><div> Type.Sphere: com.jme3.bounding.BoundingSphere is a sphere used as a container for a group of vertices of a piece of geometry. A BoundingSphere has a center and a radius.</div>
</li>
<li><div> Type.AABB = Axis-aligned bounding box. A com.jme3.bounding.BoundingBox is an axis-aligned cuboid used as a container for a group of vertices of a piece of geometry. A BoundingBox has a center and extents from that center along the x, y and z axis.</div>
</li>
<li><div> Type.OBB = Oriented bounding box. (not in use)</div>
</li>
<li><div> Type.Capsule = Cylinder with rounded ends. Often used for mobile characters.</div>
</li>
</ul>
<p>
<strong>Note:</strong> Physical objects have their own &quot;bounding volumes&quot; called CollisionShapes.
</p>
</div>
<h2><a>Collisions</a></h2>
<div>
<p>
The interface com.jme3.collision.Collidable declares one method that returns how many collisions were found between two Collidables: <code>collideWith(Collidable other, CollisionResults results)</code>.
</p>
<ul>
<li><div> A <code>com.jme3.collision.CollisionResults</code> object is an ArrayList of comparable <code>com.jme3.collision.CollisionResult</code> objects.</div>
</li>
<li><div> You can iterate over the CollisionResults to identify the other parties involved in the collision. <br/>
Note that jME counts <em>all</em> collisions, this means a ray intersecting a box will be counted as two hits, one on the front where the ray enters, and one on the back where the ray exits.</div>
</li>
</ul>
<div><table>
<tr>
<th>CollisionResults Method</th><th>Usage</th>
</tr>
<tr>
<td>size() </td><td>Returns the number of CollisionResult objects.</td>
</tr>
<tr>
<td>getClosestCollision() </td><td>Returns the CollisionResult with the lowest distance.</td>
</tr>
<tr>
<td>getFarthestCollision()</td><td>Returns the CollisionResult with the farthest distance.</td>
</tr>
<tr>
<td>getCollision(i) </td><td>Returns the CollisionResult at index i.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [2825-3153] -->
<p>
A CollisionResult object contains information about the second party of the collision event.
</p>
<div><table>
<tr>
<th>CollisionResult Method</th><th>Usage</th>
</tr>
<tr>
<td>getContactPoint()</td><td>Returns the contact point coordinate on the second party, as Vector3f.</td>
</tr>
<tr>
<td>getContactNormal()</td><td>Returns the Normal vector at the contact point, as Vector3f.</td>
</tr>
<tr>
<td>getDistance()</td><td>Returns the distance between the Collidable and the second party, as float.</td>
</tr>
<tr>
<td>getGeometry()</td><td>Returns the Geometry of the second party.</td>
</tr>
<tr>
<td>getTriangle(t)</td><td>Binds t to the triangle t on the second party&#039;s mesh that was hit.</td>
</tr>
<tr>
<td>getTriangleIndex()</td><td>Returns the index of the triangle on the second party&#039;s mesh that was hit. (?)</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [3247-3784] -->
</div>
<h3><a>Code Sample</a></h3>
<div>
<p>
Assume you have two collidables a and b and want to detect collisions between them. The collision parties can be Geometries, Nodes with Geometries attached (including the rootNode), Planes, Quads, Lines, or Rays.
</p>
<p>
The following code snippet can be triggered by listeners (e.g. after an input action such as a click), or timed in the update loop.
</p>
<pre> // Calculate detection results
CollisionResults results = new CollisionResults&#40;&#41;;
a.collideWith&#40;b, results&#41;;
System.out.println&#40;&quot;Number of Collisions between&quot; + a.getName&#40;&#41;+ &quot; and &quot;
+ b.getName&#40;&#41; &quot; : &quot; + results.size&#40;&#41;&#41;;
System.out.println&#40;&quot;Number of Collisions between&quot; +
a.getName&#40;&#41;+ &quot; and &quot; + b.getName&#40;&#41; &quot;: &quot; + results.size&#40;&#41;&#41;;
// Use the results
if &#40;results.size&#40;&#41; &gt; 0&#41; &#123;
// how to react when a collision was detected
CollisionResult closest = results.getClosestCollision&#40;&#41;;
System.out.println&#40;&quot;What was hit? &quot; + closest.getGeometry&#40;&#41;.getName&#40;&#41; &#41;;
System.out.println&#40;&quot;Where was it hit? &quot; + closest.getContactPoint&#40;&#41; &#41;;
@ -70,7 +129,12 @@ class="col1">Returns the index of the triangle on the second party&#039;s mesh t
&#125; else &#123;
// how to react when no collision occured
&#125;
&#125;</pre><p> You can also loop over all results and trigger different reactions depending on what was hit and where it was hit. In this example, we simply print info about them.</p><pre> // Calculate Results
&#125;</pre>
<p>
You can also loop over all results and trigger different reactions depending on what was hit and where it was hit. In this example, we simply print info about them.
</p>
<pre> // Calculate Results
CollisionResults results = new CollisionResults&#40;&#41;;
a.collideWith&#40;b, results&#41;;
System.out.println&#40;&quot;Number of Collisions between&quot; + a.getName&#40;&#41;+ &quot; and &quot;
@ -86,87 +150,62 @@ class="col1">Returns the index of the triangle on the second party&#039;s mesh t
System.out.println&#40;&quot;Details of Collision #&quot; + i + &quot;:&quot;&#41;;
System.out.println&#40;&quot; Party &quot; + party + &quot; was hit at &quot; + pt + &quot;, &quot; + dist + &quot; wu away.&quot;&#41;;
System.out.println&#40;&quot; The hit triangle #&quot; + tri + &quot; has a normal vector of &quot; + norm&#41;;
&#125;</pre><p> Knowing the distance of the collisions is useful for example when you intersect Lines and Rays with other objects.</p></div><h2><a
name="intersection">Intersection</a></h2><div
class="level2"><p> A com.jme3.math.Ray is an infinite line with a beginning, a direction, and no end; whereas a com.jme3.math.Line is an infinite line with only a direction (no beginning, no end).
Rays are used to detect where a 3D object is &quot;looking&quot; and whether one object can &quot;see&quot; the other.</p><ul><li
class="level1"><div
class="li"> You can determine where a user has clicked by casting a ray from the camera in the direction of the camera. Now identify the closest collision of the ray with e.g. the rootNode.</div></li><li
class="level1"><div
class="li"> Or you cast a ray from a player in the direction of another player. Then you detect all collisions of this ray with other entities (walls, foliage, window panes) and use this to calculate whether one can see the other.</div></li></ul><p> These simple ray-surface intersection tests are called Ray Casting. (As opposed to the more advanced Ray Tracing, Ray Casting does not follow a ray&#039;s reflection after the first hit, but the ray goes straight on.)</p></div><h3><a
name="usecasepicking_a_target_with_crosshairs">Usecase: Picking a target with crosshairs</a></h3><div
class="level3"><p> This <code>pick target</code> input mapping implements an action that determines what a user clicked (if you map this to a mouse click). It assumes that there are crosshairs in the center of the screen, and the user aims the crosshairs at an object in the scene. We use a ray casting approach to determine the geometry that was picked by the user. You can extend this code to do whatever with the identified target (shoot it, take it, move it, …)
Use this together with <code>inputManager.setCursorVisible(false)</code>.</p><pre> private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float intensity, float tpf&#41; &#123;
if &#40;name.equals&#40;&quot;pick target&quot;&#41;&#41; &#123;
// Reset results list.
CollisionResults results = new CollisionResults&#40;&#41;;
// Aim the ray from camera location in camera direction
// (assuming crosshairs in center of screen).
Ray ray = new Ray&#40;cam.getLocation&#40;&#41;, cam.getDirection&#40;&#41;&#41;;
// Collect intersections between ray and all nodes in results list.
rootNode.collideWith&#40;ray, results&#41;;
// Print the results so we see what is going on
for &#40;int i = 0; i &lt; results.size&#40;&#41;; i++&#41; &#123;
// For each “hit”, we know distance, impact point, geometry.
float dist = results.getCollision&#40;i&#41;.getDistance&#40;&#41;;
Vector3f pt = results.getCollision&#40;i&#41;.getContactPoint&#40;&#41;;
String target = results.getCollision&#40;i&#41;.getGeometry&#40;&#41;.getName&#40;&#41;;
System.out.println&#40;&quot;Selection #&quot; + i + &quot;: &quot; + target + &quot; at &quot; + pt + &quot;, &quot; + dist + &quot; WU away.&quot;&#41;;
&#125;
// 5. Use the results -- we rotate the selected geometry.
if &#40;results.size&#40;&#41; &gt; 0&#41; &#123;
// The closest result is the target that the player picked:
Geometry target = results.getClosestCollision&#40;&#41;.getGeometry&#40;&#41;;
// Here comes the action:
if&#40;target.getName&#40;&#41;.equals&#40;&quot;Red Box&quot;&#41;&#41;
target.rotate&#40;0, - intensity, 0&#41;;
else if&#40;target.getName&#40;&#41;.equals&#40;&quot;Blue Box&quot;&#41;&#41;
target.rotate&#40;0, intensity, 0&#41;;
&#125;
&#125; // else if ...
&#125;
&#125;;</pre></div><h3><a
name="usecasepicking_a_target_with_mouse_cursor">Usecase: Picking a target with mouse cursor</a></h3><div
class="level3"><p> This <code>pick target</code> input mapping implements an action that determines what a user clicked (if you map this to a mouse click). It assumes that the cursor is visible, and the user aims the cursor at an object in the scene. We use a ray casting approach to determine the geometry that was picked by the user. You can extend this code to do whatever with the identified target (shoot it, take it, move it, …) Use this together with <code>inputManager.setCursorVisible(true)</code>.</p><pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float intensity, float tpf&#41; &#123;
if &#40;name.equals&#40;&quot;pick target&quot;&#41;&#41; &#123;
// Reset results list.
CollisionResults results = new CollisionResults&#40;&#41;;
// Convert screen click to 3d position
Vector2f click2d = inputManager.getCursorPosition&#40;&#41;;
Vector3f click3d = cam.getWorldCoordinates&#40;new Vector2f&#40;click2d.x, click2d.y&#41;, 0f&#41;.clone&#40;&#41;;
Vector3f dir = cam.getWorldCoordinates&#40;new Vector2f&#40;click2d.x, click2d.y&#41;, 1f&#41;.subtractLocal&#40;click3d&#41;;
// Aim the ray from the clicked spot forwards.
Ray ray = new Ray&#40;click3d, dir&#41;;
// Collect intersections between ray and all nodes in results list.
rootNode.collideWith&#40;ray, results&#41;;
// (Print the results so we see what is going on:)
for &#40;int i = 0; i &lt; results.size&#40;&#41;; i++&#41; &#123;
// (For each “hit”, we know distance, impact point, geometry.)
float dist = results.getCollision&#40;i&#41;.getDistance&#40;&#41;;
Vector3f pt = results.getCollision&#40;i&#41;.getContactPoint&#40;&#41;;
String target = results.getCollision&#40;i&#41;.getGeometry&#40;&#41;.getName&#40;&#41;;
System.out.println&#40;&quot;Selection #&quot; + i + &quot;: &quot; + target + &quot; at &quot; + pt + &quot;, &quot; + dist + &quot; WU away.&quot;&#41;;
&#125;
// Use the results -- we rotate the selected geometry.
if &#40;results.size&#40;&#41; &gt; 0&#41; &#123;
// The closest result is the target that the player picked:
Geometry target = results.getClosestCollision&#40;&#41;.getGeometry&#40;&#41;;
// Here comes the action:
if &#40;target.getName&#40;&#41;.equals&#40;&quot;Red Box&quot;&#41;&#41; &#123;
target.rotate&#40;0, -intensity, 0&#41;;
&#125; else if &#40;target.getName&#40;&#41;.equals&#40;&quot;Blue Box&quot;&#41;&#41; &#123;
target.rotate&#40;0, intensity, 0&#41;;
&#125;
&#125;
&#125; // else if ...
&#125;
&#125;;</pre></div><h2><a
name="bounding_interval_hierarchy">Bounding Interval Hierarchy</a></h2><div
class="level2"><p> com.jme3.collision.bih.BIHNode
com.jme3.scene.CollisionData</p></div><h2><a
name="sweepsphere">SweepSphere</a></h2><div
class="level2"><p> A com.jme3.collision.SweepSphere implements a collidable &quot;stretched&quot; sphere that is shaped like a capsule (an upright cylinder with half a sphere on top and the second half at the bottom).
This shape is usually used to simulate simple non-physcial collisions for character entities in games. The sweep sphere can be used to check collision against a triangle or another sweep sphere.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:collision_and_intersection?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
<p>
Knowing the distance of the collisions is useful for example when you intersect Lines and Rays with other objects.
</p>
</div>
<h2><a>Intersection</a></h2>
<div>
<p>
A com.jme3.math.Ray is an infinite line with a beginning, a direction, and no end; whereas a com.jme3.math.Line is an infinite line with only a direction (no beginning, no end).
</p>
<p>
Rays are used to detect where the user or a player is &quot;looking&quot; when performing an action:
</p>
<ul>
<li><div> <strong>Click to select:</strong> You can determine what a user has clicked by casting a ray from the camera in the direction of the camera. Now identify the closest collision of the ray with the rootNode.</div>
</li>
<li><div> <strong>Line of sight:</strong> Cast a ray from a player in the direction of another player. Then you detect all collisions of this ray with other entities (walls, foliage, window panes) and use this to calculate whether one can see the other.</div>
</li>
</ul>
<p>
These simple ray-surface intersection tests are called Ray Casting. As opposed to the more advanced Ray Tracing, Ray Casting does not follow a ray&#039;s reflection after the first hit, the ray just goes straight on.
</p>
<p>
Learn how to implement <a href="/com/jme3/gde/core/docs/jme3/advanced/mouse_picking.html">Mouse Picking</a> here.
</p>
</div>
<h2><a>Bounding Interval Hierarchy</a></h2>
<div>
<p>
com.jme3.collision.bih.BIHNode
com.jme3.scene.CollisionData
</p>
</div>
<h2><a>SweepSphere</a></h2>
<div>
<p>
A com.jme3.collision.SweepSphere implements a collidable &quot;stretched&quot; sphere that is shaped like a capsule (an upright cylinder with half a sphere on top and the second half at the bottom).
This shape is usually used to simulate simple non-physcial collisions for character entities in games. The sweep sphere can be used to check collision against a triangle or another sweep sphere.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:collision_and_intersection?do=export_xhtmlbody">view online version</a></em></p>

@ -1,83 +1,177 @@
<h1><a
name="combo_moves">Combo Moves</a></h1><div
class="level1"><p> The ComboMoves class allows you to define combinations of inputs that trigger special actions. Entering an input combo correctly can bring the player incremental rewards, such as an increased chance to hit, an increased effectiveness, or decreased change of being blocked, whatever the game designer chooses. <a
href="http://en.wikipedia.org/wiki/Combo_%28video_gaming%29">More background info</a></p><p> Combos are usually a series of inputs, in a fixed order: For example a keyboard combo can look like: &quot;press Down, then Down+Right together, then Right&quot;.</p><p> Usage:</p><ol><li
class="level1"><div
class="li"> Create input triggers</div></li><li
class="level1"><div
class="li"> Define combos</div></li><li
class="level1"><div
class="li"> Detect combos in ActionListener</div></li><li
class="level1"><div
class="li"> Execute combos in update loop</div></li></ol><p> Copy the two classes ComboMoveExecution.java and ComboMove.java into your application and adjust them to your package paths.</p></div><h2><a
name="example_code">Example Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/TestComboMoves.java">TestComboMoves.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/ComboMoveExecution.java">ComboMoveExecution.java</a> ← required</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/ComboMove.java">ComboMove.java</a> ← required</div></li></ul></div><h2><a
name="create_input_triggers">Create Input Triggers</a></h2><div
class="level2"><p> First you <a
href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">define your game&#039;s inputs</a> as you usually do: Implement the com.jme3.input.controls.ActionListener interface for your class, and add triggers mappings such as com.jme3.input.controls.KeyTrigger and com.jme3.input.KeyInput.</p><p> For example:</p><pre>inputManager.addMapping&#40;&quot;Left&quot;, new KeyTrigger&#40;KeyInput.KEY_LEFT&#41;&#41;;
<h1><a>Combo Moves</a></h1>
<div>
<p>
The ComboMoves class allows you to define combinations of inputs that trigger special actions. Entering an input combo correctly can bring the player incremental rewards, such as an increased chance to hit, an increased effectiveness, or decreased change of being blocked, whatever the game designer chooses. <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/Combo_%28video_gaming%29"><param name="text" value="<html><u>More background info</u></html>"><param name="textColor" value="blue"></object>
</p>
<p>
Combos are usually a series of inputs, in a fixed order: For example a keyboard combo can look like: &quot;press Down, then Down+Right together, then Right&quot;.
</p>
<p>
Usage:
</p>
<ol>
<li><div> Create input triggers </div>
</li>
<li><div> Define combos</div>
</li>
<li><div> Detect combos in ActionListener </div>
</li>
<li><div> Execute combos in update loop </div>
</li>
</ol>
<p>
Copy the two classes ComboMoveExecution.java and ComboMove.java into your application and adjust them to your package paths.
</p>
</div>
<h2><a>Example Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/TestComboMoves.java"><param name="text" value="<html><u>TestComboMoves.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/ComboMoveExecution.java"><param name="text" value="<html><u>ComboMoveExecution.java</u></html>"><param name="textColor" value="blue"></object> ← required</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/combomoves/ComboMove.java"><param name="text" value="<html><u>ComboMove.java</u></html>"><param name="textColor" value="blue"></object> ← required</div>
</li>
</ul>
</div>
<h2><a>Create Input Triggers</a></h2>
<div>
<p>
First you <a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">define your game&#039;s inputs</a> as you usually do: Implement the com.jme3.input.controls.ActionListener interface for your class, and add triggers mappings such as com.jme3.input.controls.KeyTrigger and com.jme3.input.KeyInput.
</p>
<p>
For example:
</p>
<pre>inputManager.addMapping&#40;&quot;Left&quot;, new KeyTrigger&#40;KeyInput.KEY_LEFT&#41;&#41;;
inputManager.addMapping&#40;&quot;Right&quot;, new KeyTrigger&#40;KeyInput.KEY_RIGHT&#41;&#41;;
inputManager.addMapping&#40;&quot;Up&quot;, new KeyTrigger&#40;KeyInput.KEY_UP&#41;&#41;;
inputManager.addMapping&#40;&quot;Down&quot;, new KeyTrigger&#40;KeyInput.KEY_DOWN&#41;&#41;;
inputManager.addMapping&#40;&quot;Attack1&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;
...
inputManager.addListener&#40;this, &quot;Left&quot;, &quot;Right&quot;, &quot;Up&quot;, &quot;Down&quot;, &quot;Attack1&quot;&#41;;</pre></div><h2><a
name="define_combos">Define Combos</a></h2><div
class="level2"><p> For each of your combo moves, you specify the series of inputs that will trigger it. The order in which you define them is the order the player has to press them for the step to be recorded. When all steps have been recorded, the combo is triggered.</p><p> The following example shows how a fireball combo move is triggered by pressing the navigation keys for &quot;down, down+right, right&quot;, in this order.</p><pre>ComboMove fireball = new ComboMove&#40;&quot;Fireball&quot;&#41;;
inputManager.addListener&#40;this, &quot;Left&quot;, &quot;Right&quot;, &quot;Up&quot;, &quot;Down&quot;, &quot;Attack1&quot;&#41;;</pre>
</div>
<h2><a>Define Combos</a></h2>
<div>
<p>
For each of your combo moves, you specify the series of inputs that will trigger it. The order in which you define them is the order the player has to press them for the step to be recorded. When all steps have been recorded, the combo is triggered.
</p>
<p>
The following example shows how a fireball combo move is triggered by pressing the navigation keys for &quot;down, down+right, right&quot;, in this order.
</p>
<pre>ComboMove fireball = new ComboMove&#40;&quot;Fireball&quot;&#41;;
fireball.press&#40;&quot;Down&quot;&#41;.notPress&#40;&quot;Right&quot;&#41;.done&#40;&#41;;
fireball.press&#40;&quot;Right&quot;, &quot;Down&quot;&#41;.done&#40;&#41;;
fireball.press&#40;&quot;Right&quot;&#41;.notPress&#40;&quot;Down&quot;&#41;.done&#40;&#41;;
fireball.notPress&#40;&quot;Right&quot;, &quot;Down&quot;&#41;.done&#40;&#41;;
fireball.setUseFinalState&#40;false&#41;;</pre><p> Also create a ComboMoveExecution object for each ComboMove. You need it later to execute the detected combo.</p><pre>ComboMoveExecution fireballExec = new ComboMoveExecution&#40;fireball&#41;;</pre></div><h3><a
name="combomove_class_methods">ComboMove Class Methods</a></h3><div
class="level3"><p> Use the following ComboMove methods to specify the combo:</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">ComboMove Method</th><th
class="col1">Description</th></tr><tr
class="row1"><td
class="col0">press(&quot;A&quot;).done(); <br/> press(&quot;A&quot;,&quot;B&quot;).done();</td><td
class="col1">Combo step is recorded if A is entered. <br/> Combo step is recorded if A and B are entered simultaneously.</td></tr><tr
class="row2"><td
class="col0">notPress(&quot;A&quot;).done(); <br/> notPress(&quot;A&quot;,&quot;B&quot;).done();</td><td
class="col1">Combo step is recorded if A is released. <br/> Combo step is recorded if A and B are both released.</td></tr><tr
class="row3"><td
class="col0">press(&quot;A&quot;).notPress(&quot;B&quot;).done();</td><td
class="col1">Combo step is recorded if A is entered, and not B</td></tr><tr
class="row4"><td
class="col0">press(&quot;A&quot;).notPress(&quot;B&quot;).timeElapsed(0.11f).done();</td><td
class="col1">Combo step is recorded a certain time after A and not B is entered. <br/> etc, etc …</td></tr><tr
class="row5"><td
class="col0">setPriority(0.5f);</td><td
class="col1">If there is an ambiguity, a high-priority combo will trigger instead of a low-priority combo. This prevents that a similar looking combo step &quot;hijacks&quot; another Combo. Use only once per ComboMove.</td></tr><tr
class="row6"><td
class="col0">setUseFinalState(false); <br/> setUseFinalState(true);</td><td
class="col1">This is the final command of the series. <br/> False: Do not wait on a final state, chain combo steps. (?) <br/> True: This is the final state, do not chain combo steps. (?)</td></tr></table></div><p> The <code>press()</code> and <code>notPress()</code> methods accept sets of Input Triggers, e.g. <code>fireball.press(&quot;A&quot;,&quot;B&quot;,&quot;C&quot;).done()</code>.</p><p> The following getters give you more information about the game state:</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">ComboMove Method</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">getCastTime()</td><td
class="col1">Returns the time since the last step has been recorded. (?)</td></tr><tr
class="row2"><td
class="col0">getMoveName()</td><td
class="col1">Returns the string of the current combo</td></tr><tr
class="row3"><td
class="col0">getPriority()</td><td
class="col1">Returns the priority of this move</td></tr></table></div></div><h2><a
name="detect_combos_in_actionlistener">Detect Combos in ActionListener</a></h2><div
class="level2"><p> Now that you have specified the combo steps, you want to detect them. You do that in the onAction() method that you get from the ActionListener interface.</p><p> Create a HashSet <code>pressMappings</code> to track curently pressed mappings, and a ComboMove object <code>currentMove</code> to track the current move.</p><p> We also track the cast time of a combo to determine if it has timed out (see update loop below).</p><pre>private HashSet&lt;String&gt; pressedMappings = new HashSet&lt;String&gt;&#40;&#41;;
fireball.setUseFinalState&#40;false&#41;;</pre>
<p>
Also create a ComboMoveExecution object for each ComboMove. You need it later to execute the detected combo.
</p>
<pre>ComboMoveExecution fireballExec = new ComboMoveExecution&#40;fireball&#41;;</pre>
</div>
<h3><a>ComboMove Class Methods</a></h3>
<div>
<p>
Use the following ComboMove methods to specify the combo:
</p>
<div><table>
<tr>
<th>ComboMove Method</th><th>Description</th>
</tr>
<tr>
<td>press(&quot;A&quot;).done(); <br/>
press(&quot;A&quot;,&quot;B&quot;).done();</td><td>Combo step is recorded if A is entered. <br/>
Combo step is recorded if A and B are entered simultaneously.</td>
</tr>
<tr>
<td>notPress(&quot;A&quot;).done(); <br/>
notPress(&quot;A&quot;,&quot;B&quot;).done();</td><td>Combo step is recorded if A is released. <br/>
Combo step is recorded if A and B are both released.</td>
</tr>
<tr>
<td>press(&quot;A&quot;).notPress(&quot;B&quot;).done();</td><td>Combo step is recorded if A is entered, and not B</td>
</tr>
<tr>
<td>press(&quot;A&quot;).notPress(&quot;B&quot;).timeElapsed(0.11f).done();</td><td>Combo step is recorded a certain time after A and not B is entered. <br/>
etc, etc …</td>
</tr>
<tr>
<td>setPriority(0.5f);</td><td>If there is an ambiguity, a high-priority combo will trigger instead of a low-priority combo. This prevents that a similar looking combo step &quot;hijacks&quot; another Combo. Use only once per ComboMove.</td>
</tr>
<tr>
<td>setUseFinalState(false); <br/>
setUseFinalState(true);</td><td>This is the final command of the series. <br/>
False: Do not wait on a final state, chain combo steps. (?) <br/>
True: This is the final state, do not chain combo steps. (?)</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3096-4090] -->
<p>
The <code>press()</code> and <code>notPress()</code> methods accept sets of Input Triggers, e.g. <code>fireball.press(&quot;A&quot;,&quot;B&quot;,&quot;C&quot;).done()</code>.
</p>
<p>
The following getters give you more information about the game state:
</p>
<div><table>
<tr>
<th>ComboMove Method</th><th>Usage</th>
</tr>
<tr>
<td>getCastTime()</td><td>Returns the time since the last step has been recorded. (?)</td>
</tr>
<tr>
<td>getMoveName()</td><td>Returns the string of the current combo</td>
</tr>
<tr>
<td>getPriority()</td><td>Returns the priority of this move</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [4283-4489] -->
</div>
<h2><a>Detect Combos in ActionListener</a></h2>
<div>
<p>
Now that you have specified the combo steps, you want to detect them. You do that in the onAction() method that you get from the ActionListener interface.
</p>
<p>
Create a HashSet <code>pressMappings</code> to track curently pressed mappings, and a ComboMove object <code>currentMove</code> to track the current move.
</p>
<p>
We also track the cast time of a combo to determine if it has timed out (see update loop below).
</p>
<pre>private HashSet&lt;String&gt; pressedMappings = new HashSet&lt;String&gt;&#40;&#41;;
private ComboMove currentMove = null;
private float currentMoveCastTime = 0;
private float time = 0;
@ -117,9 +211,18 @@ public void onAction&#40;String name, boolean isPressed, float tpf&#41; &#123;
currentMove = toExec;
currentMoveCastTime = currentMove.getCastTime&#40;&#41;;
&#125;
&#125;</pre></div><h2><a
name="execute_combos_in_the_update_loop">Execute Combos in the Update Loop</a></h2><div
class="level2"><p> Now that you have detected the current move, you want to execute it. You do that in the update loop.</p><pre>@Override
&#125;</pre>
</div>
<h2><a>Execute Combos in the Update Loop</a></h2>
<div>
<p>
Now that you have detected the current move, you want to execute it. You do that in the update loop.
</p>
<pre>@Override
public void simpleUpdate&#40;float tpf&#41;&#123;
time += tpf;
fireballExec.updateExpiration&#40;time&#41;;
@ -134,15 +237,33 @@ public void simpleUpdate&#40;float tpf&#41;&#123;
currentMove = null;
&#125;
&#125;
&#125;</pre><p> Test <code>currentMove.getMoveName()</code> and proceed to call methods that implement any special actions and bonuses. This is up to you and depends individually on your game.</p></div><h2><a
name="why_combos">Why Combos?</a></h2><div
class="level2"><p> Depending on the game genre, the designer can reward the players&#039; intrinsical or extrinsical skills:</p><ul><li
class="level1"><div
class="li"> (intrinsical:) RPGs typically calculate the success of an attack from the character&#039;s in-game training level: The player plays the role of a character whose skill level is defined in numbers. RPGs typically do not offer any Combos.</div></li><li
class="level1"><div
class="li"> (extrinsical:) Sport and fighter games typically choose to reward the player&#039;s &quot;manual&quot; skills: The success of a special move solely depends on the player&#039;s own dexterity. These games typically offer optional Combos.</div></li></ul><div
class="tags"><span> <a
href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>, <a
href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:combo_moves?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
<p>
Test <code>currentMove.getMoveName()</code> and proceed to call methods that implement any special actions and bonuses. This is up to you and depends individually on your game.
</p>
</div>
<h2><a>Why Combos?</a></h2>
<div>
<p>
Depending on the game genre, the designer can reward the players&#039; intrinsical or extrinsical skills:
</p>
<ul>
<li><div> (intrinsical:) RPGs typically calculate the success of an attack from the character&#039;s in-game training level: The player plays the role of a character whose skill level is defined in numbers. RPGs typically do not offer any Combos.</div>
</li>
<li><div> (extrinsical:) Sport and fighter games typically choose to reward the player&#039;s &quot;manual&quot; skills: The success of a special move solely depends on the player&#039;s own dexterity. These games typically offer optional Combos.</div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:combo_moves?do=export_xhtmlbody">view online version</a></em></p>

@ -1,42 +1,83 @@
<h1><a
name="custom_controls">Custom Controls</a></h1><div
class="level1"><p> A <code>com.jme3.scene.control.Control</code> is a customizable jME3 interface that allows you to cleanly implement game logic, such as game rules, or artificially intelligent behaviour in NPCs. You use Controls to control the behaviour of types of spatials. To control global game behaviour see <a
href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> – you can use both together.
To control the behaviour of types of entities:</p><ol><li
class="level1"><div
class="li"> Create one control for each type of behavior. When you add several controls to one spatial, they will be executed in the order they were added. <br/> For example, an NPC can be controlled by a PhysicsControl and an AIControl.</div></li><li
class="level1"><div
class="li"> You define a custom control and implement its behaviour in the Control&#039;s update() method.</div><ul><li
class="level2"><div
class="li"> In the control, you can pass arguments and manipulate the spatial in any way: Modify its transformation (move, scale, rotate), play animations, check for enemies around it and react, etc.</div></li></ul></li><li
class="level1"><div
class="li"> Add the control to a spatial and the Spatial&#039;s game state is updated automatically from now on. <br/> <code>spatial.addControl(myControl)</code></div></li></ol><p> To implement game logic for a type of spatial, you will either extend AbstractControl, or implement the Control interface, as explained in this article.</p></div><h2><a
name="usage_examples">Usage Examples</a></h2><div
class="level2"><p> For example, you could write a CharacterAnimControl that animates a character accordingly while it is being moved by a CharacterControl. Or you can write an AIControl that remote-controls NPC behaviour in fight situatons. Or you could write a DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile… The possibilities are endless. <img
src="/wiki/lib/images/smileys/icon_smile.gif" class="middle" alt=":-)" /> Existing examples in the code base include:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/animation/AnimControl.java">AnimControl.java</a> allows manipulation of skeletal animation, including blending and multiple channels.</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/control/CameraControl.java">CameraControl.java</a> allows you to sync the camera position with the position of a given spatial.</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/control/BillboardControl.java">BillboardControl.java</a> displays a flat picture orthogonally, e.g. a speech bubble or informational dialog.</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/#src%2Fjbullet%2Fcom%2Fjme3%2Fbullet%2Fcontrol">PhysicsControl</a> subclasses (such as CharacterControl, RigidBodyControl, VehicleControl) allow you to add physical properties to any spatial. PhysicsControls tie into capabilities provided by the BulletAppState.</div></li></ul></div><h2><a
name="the_control_interface">The Control Interface</a></h2><div
class="level2"><p> The interface can be found under <code>com.jme3.scene.control.Control</code>. It has the following method signatures:</p><ul><li
class="level1"><div
class="li"> <code>cloneForSpatial(Spatial)</code>: Clones the Control and attaches it to a clone of the given Spatial. The AssetManager uses this method if the same spatial is loaded twice. You can specify which fields you want your object to reuse (e.g. collisionshapes) in this case.</div></li><li
class="level1"><div
class="li"> <code>setEnabled(boolean)</code>: Enable or disable the control. If disabled, update() does nothing. Goes with accessor <code>isEnabled();</code>.</div></li><li
class="level1"><div
class="li"> There are also some internal methods that you do not call from user code: <code>setSpatial(Spatial s)</code>, <code>update(float tpf);</code>, <code>render(RenderManager rm, ViewPort vp)</code>.</div></li></ul><p> If you want to create a Control that also extends an existing class, then create a custom extension of the Control Interface. Usage example:
1. Create a custom control interface</p><pre>public interface MyControl extends Control &#123;
<h1><a>Custom Controls</a></h1>
<div>
<p>
A <code>com.jme3.scene.control.Control</code> is a customizable jME3 interface that allows you to cleanly implement game logic, such as game rules, or artificially intelligent behaviour in NPCs. You use Controls to control the behaviour of types of spatials. To control global game behaviour see <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> – you can use both together.
To control the behaviour of types of entities:
</p>
<ol>
<li><div> Create one control for each type of behavior. When you add several controls to one spatial, they will be executed in the order they were added. <br/>
For example, an NPC can be controlled by a PhysicsControl and an AIControl.</div>
</li>
<li><div> You define a custom control and implement its behaviour in the Control&#039;s update() method.</div>
<ul>
<li><div> In the control, you can pass arguments and manipulate the spatial in any way: Modify its transformation (move, scale, rotate), play animations, check for enemies around it and react, etc.</div>
</li>
</ul>
</li>
<li><div> Add the control to a spatial and the Spatial&#039;s game state is updated automatically from now on. <br/>
<code>spatial.addControl(myControl)</code></div>
</li>
</ol>
<p>
To implement game logic for a type of spatial, you will either extend AbstractControl, or implement the Control interface, as explained in this article.
</p>
</div>
<h2><a>Usage Examples</a></h2>
<div>
<p>
For example, you could write a CharacterAnimControl that animates a character accordingly while it is being moved by a CharacterControl. Or you can write an AIControl that remote-controls NPC behaviour in fight situatons. Or you could write a DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile… The possibilities are endless. <img src="/wiki/lib/images/smileys/icon_smile.gif" class="middle" alt=":-)" />
Existing examples in the code base include:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/animation/AnimControl.java"><param name="text" value="<html><u>AnimControl.java</u></html>"><param name="textColor" value="blue"></object> allows manipulation of skeletal animation, including blending and multiple channels.</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/control/CameraControl.java"><param name="text" value="<html><u>CameraControl.java</u></html>"><param name="textColor" value="blue"></object> allows you to sync the camera position with the position of a given spatial.</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/control/BillboardControl.java"><param name="text" value="<html><u>BillboardControl.java</u></html>"><param name="textColor" value="blue"></object> displays a flat picture orthogonally, e.g. a speech bubble or informational dialog.</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/#src%2Fjbullet%2Fcom%2Fjme3%2Fbullet%2Fcontrol"><param name="text" value="<html><u>PhysicsControl</u></html>"><param name="textColor" value="blue"></object> subclasses (such as CharacterControl, RigidBodyControl, VehicleControl) allow you to add physical properties to any spatial. PhysicsControls tie into capabilities provided by the BulletAppState.</div>
</li>
</ul>
</div>
<h2><a>The Control Interface</a></h2>
<div>
<p>
The interface can be found under <code>com.jme3.scene.control.Control</code>. It has the following method signatures:
</p>
<ul>
<li><div> <code>cloneForSpatial(Spatial)</code>: Clones the Control and attaches it to a clone of the given Spatial. The AssetManager uses this method if the same spatial is loaded twice. You can specify which fields you want your object to reuse (e.g. collisionshapes) in this case. </div>
</li>
<li><div> <code>setEnabled(boolean)</code>: Enable or disable the control. If disabled, update() does nothing. Goes with accessor <code>isEnabled();</code>.</div>
</li>
<li><div> There are also some internal methods that you do not call from user code: <code>setSpatial(Spatial s)</code>, <code>update(float tpf);</code>, <code>render(RenderManager rm, ViewPort vp)</code>.</div>
</li>
</ul>
<p>
If you want to create a Control that also extends an existing class, then create a custom extension of the Control Interface. Usage example:
1. Create a custom control interface
</p>
<pre>public interface MyControl extends Control &#123;
public void setSomething&#40;int x&#41;; // add your custom methods
&#125;</pre><p> 2. Create custom classes implementing your control interface</p><pre>public class ControlledThing extends MyThing implements MyControl &#123;
&#125;</pre>
<p>
2. Create custom classes implementing your control interface
</p>
<pre>public class ControlledThing extends MyThing implements MyControl &#123;
protected Spatial spatial;
protected boolean enabled = true;
public ControlledThing&#40;&#41; &#123; &#125;
@ -90,15 +131,30 @@ class="li"> There are also some internal methods that you do not call from user
spatial = &#40;Spatial&#41; ic.readSavable&#40;&quot;spatial&quot;, null&#41;;
// read custom variables ....
&#125;
&#125;</pre></div><h2><a
name="abstractcontrol">AbstractControl</a></h2><div
class="level2"><p> This class can be found under <code>com.jme3.scene.control.AbstractControl</code>.</p><ul><li
class="level1"><div
class="li"> This is a default abstract class that implements the Control interface.</div></li><li
class="level1"><div
class="li"> It gives you access to a boolean <code>enabled</code>, and a Spatial <code>spatial</code>.</div></li><li
class="level1"><div
class="li"> Extend AbstractControl to create a custom Control.</div></li></ul><p> Usage: Your custom subclass must implement the three methods <code>controlUpdate()</code>, <code>controlRender()</code>, and <code>cloneForSpatial()</code> as shown here:</p><pre>public class MyControl extends AbstractControl implements Savable, Cloneable &#123;
&#125;</pre>
</div>
<h2><a>AbstractControl</a></h2>
<div>
<p>
This class can be found under <code>com.jme3.scene.control.AbstractControl</code>.
</p>
<ul>
<li><div> This is a default abstract class that implements the Control interface.</div>
</li>
<li><div> It gives you access to a boolean <code>enabled</code>, and a Spatial <code>spatial</code>.</div>
</li>
<li><div> Extend AbstractControl to create a custom Control.</div>
</li>
</ul>
<p>
Usage: Your custom subclass must implement the three methods <code>controlUpdate()</code>, <code>controlRender()</code>, and <code>cloneForSpatial()</code> as shown here:
</p>
<pre>public class MyControl extends AbstractControl implements Savable, Cloneable &#123;
private Thing thing; // some custom class of yours
public MyControl&#40;&#41;&#123;&#125; // empty serialization constructor
public MyControl&#40;thing&#41; &#123; // some custom constructor
@ -131,11 +187,19 @@ class="li"> Extend AbstractControl to create a custom Control.</div></li></ul><p
super.write&#40;ex&#41;;
// ex.getCapsule(this).write(...);
&#125;
&#125;</pre></div><h2><a
name="best_practices">Best Practices</a></h2><div
class="level2"><p> <strong>Tip:</strong> Use the getControl() accessor to get Control objects from Spatials. No need to pass around lots of object references.
Here an example from the <a
href="http://code.google.com/p/monkeyzone/">MonkeyZone</a> code:</p><pre>public class CharacterAnimControl implements Control &#123;
&#125;</pre>
</div>
<h2><a>Best Practices</a></h2>
<div>
<p>
<strong>Tip:</strong> Use the getControl() accessor to get Control objects from Spatials. No need to pass around lots of object references.
Here an example from the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/monkeyzone/"><param name="text" value="<html><u>MonkeyZone</u></html>"><param name="textColor" value="blue"></object> code:
</p>
<pre>public class CharacterAnimControl implements Control &#123;
...
public void setSpatial&#40;Spatial spatial&#41; &#123;
...
@ -143,16 +207,52 @@ href="http://code.google.com/p/monkeyzone/">MonkeyZone</a> code:</p><pre>public
characterControl = spatial.getControl&#40;CharacterControl.class&#41;;
...
&#125;
&#125;</pre><p> <strong>Tip:</strong> You can create custom Control interfaces so a set of different Controls provide the same methods and can be accessed with the interface class type.</p><pre>public interface ManualControl extends Control &#123;
&#125;</pre>
<p>
<strong>Tip:</strong> You can create custom Control interfaces so a set of different Controls provide the same methods and can be accessed with the interface class type.
</p>
<pre>public interface ManualControl extends Control &#123;
public void steerX&#40;float value&#41;;
public void steerY&#40;float value&#41;;
public void moveX&#40;float value&#41;;
public void moveY&#40;float value&#41;;
public void moveZ&#40;float value&#41;;
...
&#125;</pre><p> Then you create custom sub-Controls and implement the methods accordingly to the context:</p><pre>public class ManualVehicleControl extends ManualControl &#123;...&#125;</pre><p> and</p><pre>public class ManualCharacterControl extends ManualControl &#123;...&#125;</pre><p> Then add the appropriate controls to spatials:</p><pre>characterSpatial.addControl&#40;new ManualCharacterControl&#40;&#41;&#41;;
&#125;</pre>
<p>
Then you create custom sub-Controls and implement the methods accordingly to the context:
</p>
<pre>public class ManualVehicleControl extends ManualControl &#123;...&#125;</pre>
<p>
and
</p>
<pre>public class ManualCharacterControl extends ManualControl &#123;...&#125;</pre>
<p>
Then add the appropriate controls to spatials:
</p>
<pre>characterSpatial.addControl&#40;new ManualCharacterControl&#40;&#41;&#41;;
...
vehicleSpatial.addControl&#40;new ManualVehicleControl&#40;&#41;&#41;;
...</pre><p> <strong>Tip:</strong> Use the getControl() method on a Spatial to get a specific Control object, and activate its behaviour!</p><pre>ManualControl c = mySpatial.getControl&#40;ManualControl.class&#41;;
c.steerX&#40;steerX&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_controls?do=export_xhtmlbody">view online version</a></em></p>
...</pre>
<p>
<strong>Tip:</strong> Use the getControl() method on a Spatial to get a specific Control object, and activate its behaviour!
</p>
<pre>ManualControl c = mySpatial.getControl&#40;ManualControl.class&#41;;
c.steerX&#40;steerX&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_controls?do=export_xhtmlbody">view online version</a></em></p>

@ -1,77 +1,202 @@
<h1><a
name="custom_mesh_shapes">Custom Mesh Shapes</a></h1><div
class="level1"><p> <a
href="/wiki/lib/exe/fetch.php?hash=f71f7a&amp;media=http%3A%2F%2Fimg821.imageshack.us%2Fimg821%2F1829%2Fhellomesh.png"><img
src="/wiki/lib/exe/fetch.php?hash=f71f7a&amp;w=200&amp;h=150&amp;media=http%3A%2F%2Fimg821.imageshack.us%2Fimg821%2F1829%2Fhellomesh.png" class="medialeft" align="left" alt="" width="200" height="150" /></a></p><p> Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code!</p><p> In this tutorial, we (re)create a very simple rectangular mesh, and we have a look at different ways of coloring it. A flat rectangle may not look useful because it&#039;s exactly the same as a <code>com.jme3.scene.shape.Quad</code>. We choose this simple example in order to show you how to build any shape out of triangles – without the distractions of more complex shapes.</p><ul><li
class="level1"><div
class="li"> Full code sample: <a
href="http://jmonkeyengine.googlecode.com/svn/branches/stable-alpha4/engine/src/test/jme3test/model/shape/TestCustomMesh.java">TestCustomMesh.java</a></div></li></ul></div><h2><a
name="polygon_meshes">Polygon Meshes</a></h2><div
class="level2"><p> Polygon meshes are made up of triangles. The corners of the triangles are vertices. So, when ever you create a new shape, you break it down into triangles.</p><p> Let&#039;s look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to create a cube mesh. You also need to know the 8 corner coordinates (vertices). The trick is that you have to specify the vertices in a certain order: Each triangle separately, counter-clockwise.</p><p> Sounds worse than it is – here is an example:</p></div><h2><a
name="creating_a_quad_mesh">Creating a Quad Mesh</a></h2><div
class="level2"><p> Okay, we want to create a Quad. A quad has four vertices, and is made up of two triangles.</p><p> The base class for creating meshes is <code>com.jme3.scene.Mesh</code>.</p><pre>Mesh m = new Mesh&#40;&#41;;</pre></div><h3><a
name="vertices">Vertices</a></h3><div
class="level3"><p> To define your own shape, determine its vertex positions in space. Store them in an array using com.jme3.math.Vector3f. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array <code>vertices[]</code>.</p><pre>Vector3f &#91;&#93; vertices = new Vector3f&#91;4&#93;;
<h1><a>Custom Mesh Shapes</a></h1>
<div>
<p>
<img src="/wiki/lib/exe/fetch.php">
Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code!
In this tutorial, we (re)create a very simple rectangular mesh, and we have a look at different ways of coloring it. A flat rectangle may not look useful because it&#039;s exactly the same as a <code>com.jme3.scene.shape.Quad</code>. We choose this simple example in order to show you how to build any shape out of triangles – without the distractions of more complex shapes.
</p>
<ul>
<li><div> Full code sample: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.googlecode.com/svn/branches/stable-alpha4/engine/src/test/jme3test/model/shape/TestCustomMesh.java"><param name="text" value="<html><u>TestCustomMesh.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Polygon Meshes</a></h2>
<div>
<p>
Polygon meshes are made up of triangles. The corners of the triangles are vertices. So, when ever you create a new shape, you break it down into triangles.
Let&#039;s look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to create a cube mesh. You also need to know the 8 corner coordinates (vertices). The trick is that you have to specify the vertices in a certain order: Each triangle separately, counter-clockwise.
Sounds worse than it is – here is an example:
</p>
</div>
<h2><a>Creating a Quad Mesh</a></h2>
<div>
<p>
Okay, we want to create a Quad. A quad has four vertices, and is made up of two triangles.
The base class for creating meshes is <code>com.jme3.scene.Mesh</code>.
</p>
<pre>Mesh m = new Mesh&#40;&#41;;</pre>
</div>
<h3><a>Vertices</a></h3>
<div>
<p>
To define your own shape, determine its vertex positions in space. Store them in an array using com.jme3.math.Vector3f. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array <code>vertices[]</code>.
</p>
<pre>Vector3f &#91;&#93; vertices = new Vector3f&#91;4&#93;;
vertices&#91;0&#93; = new Vector3f&#40;0,0,0&#41;;
vertices&#91;1&#93; = new Vector3f&#40;3,0,0&#41;;
vertices&#91;2&#93; = new Vector3f&#40;0,3,0&#41;;
vertices&#91;3&#93; = new Vector3f&#40;3,3,0&#41;;</pre></div><h3><a
name="texture_coordinates">Texture Coordinates</a></h3><div
class="level3"><p> Next, define the Quad&#039;s 2D texture coordinates for each vertex, in the same order: Bottom left, bottom right, top left, top right. We name this array <code>texCoord[]</code></p><pre>Vector2f&#91;&#93; texCoord = new Vector2f&#91;4&#93;;
vertices&#91;3&#93; = new Vector3f&#40;3,3,0&#41;;</pre>
</div>
<h3><a>Texture Coordinates</a></h3>
<div>
<p>
Next, define the Quad&#039;s 2D texture coordinates for each vertex, in the same order: Bottom left, bottom right, top left, top right. We name this array <code>texCoord[]</code>
</p>
<pre>Vector2f&#91;&#93; texCoord = new Vector2f&#91;4&#93;;
texCoord&#91;0&#93; = new Vector2f&#40;0,0&#41;;
texCoord&#91;1&#93; = new Vector2f&#40;1,0&#41;;
texCoord&#91;2&#93; = new Vector2f&#40;0,1&#41;;
texCoord&#91;3&#93; = new Vector2f&#40;1,1&#41;;</pre></div><h3><a
name="connecting_the_dots">Connecting the Dots</a></h3><div
class="level3"><p> Next we turn the unrelated coordinates into triangles – We define the order in which the mesh is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. Note that you must specify the vertices counter-clockwise!</p><pre>int &#91;&#93; indexes = &#123; 2,0,1, 1,3,2 &#125;;</pre><ul><li
class="level1"><div
class="li"> The 2,0,1 triangle starts at top left, continues bottom left, and ends at bottom right.</div></li><li
class="level1"><div
class="li"> The 1,3,2 triangle start at bottom right, continues top right, and ends at top left.</div></li></ul><pre>2\2--3
texCoord&#91;3&#93; = new Vector2f&#40;1,1&#41;;</pre>
</div>
<h3><a>Connecting the Dots</a></h3>
<div>
<p>
Next we turn the unrelated coordinates into triangles – We define the order in which the mesh is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. Note that you must specify the vertices counter-clockwise!
</p>
<pre>int &#91;&#93; indexes = &#123; 2,0,1, 1,3,2 &#125;;</pre>
<ul>
<li><div> The 2,0,1 triangle starts at top left, continues bottom left, and ends at bottom right.</div>
</li>
<li><div> The 1,3,2 triangle start at bottom right, continues top right, and ends at top left.</div>
</li>
</ul>
<pre>2\2--3
| \ | Counter-clockwise
| \ |
0--1\1</pre></div><h3><a
name="setting_the_mesh_buffer">Setting the Mesh Buffer</a></h3><div
class="level3"><p> The Mesh data is stored in a buffer.</p><ol><li
class="level1"><div
class="li"> Using <code>com.jme3.util.BufferUtils</code>, we create three buffers for the three types of information we have:</div><ul><li
class="level2"><div
class="li"> vertex positions,</div></li><li
class="level2"><div
class="li"> texture coordinates,</div></li><li
class="level2"><div
class="li"> indices.</div></li></ul></li><li
class="level1"><div
class="li"> We assign the data to the appropriate type of buffer inside the mesh object. The three buffer types are taken from an enum in <code>com.jme3.scene.VertexBuffer.Type</code>.</div></li><li
class="level1"><div
class="li"> The third parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are single ints.</div></li><li
class="level1"><div
class="li"> In order for JMonkey to correctly show the mesh in the scene, it needs to know the bounds of our new mesh. This can easily be achieved by calling the updateBound() method on it.</div></li></ol><pre>m.setBuffer&#40;Type.Position, 3, BufferUtils.createFloatBuffer&#40;vertices&#41;&#41;;
0--1\1</pre>
</div>
<h3><a>Setting the Mesh Buffer</a></h3>
<div>
<p>
The Mesh data is stored in a buffer.
</p>
<ol>
<li><div> Using <code>com.jme3.util.BufferUtils</code>, we create three buffers for the three types of information we have:</div>
<ul>
<li><div> vertex positions,</div>
</li>
<li><div> texture coordinates,</div>
</li>
<li><div> indices.</div>
</li>
</ul>
</li>
<li><div> We assign the data to the appropriate type of buffer inside the mesh object. The three buffer types are taken from an enum in <code>com.jme3.scene.VertexBuffer.Type</code>.</div>
</li>
<li><div> The third parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are single ints.</div>
</li>
<li><div> In order for JMonkey to correctly show the mesh in the scene, it needs to know the bounds of our new mesh. This can easily be achieved by calling the updateBound() method on it.</div>
</li>
</ol>
<pre>m.setBuffer&#40;Type.Position, 3, BufferUtils.createFloatBuffer&#40;vertices&#41;&#41;;
m.setBuffer&#40;Type.TexCoord, 2, BufferUtils.createFloatBuffer&#40;texCoord&#41;&#41;;
m.setBuffer&#40;Type.Index, 1, BufferUtils.createIntBuffer&#40;indexes&#41;&#41;;
m.updateBound&#40;&#41;;</pre><p> Our Mesh is ready! Now we want to see it.</p></div><h2><a
name="using_the_mesh_in_a_scene">Using the Mesh in a Scene</a></h2><div
class="level2"><p> We create a <code>com.jme3.scene.Geometry</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.</p><pre>Geometry geom = new Geometry&#40;&quot;OurMesh&quot;, m&#41;;
m.updateBound&#40;&#41;;</pre>
<p>
Our Mesh is ready! Now we want to see it.
</p>
</div>
<h2><a>Using the Mesh in a Scene</a></h2>
<div>
<p>
We create a <code>com.jme3.scene.Geometry</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.
</p>
<pre>Geometry geom = new Geometry&#40;&quot;OurMesh&quot;, m&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/SolidColor.j3md&quot;&#41;;
mat.setColor&#40;&quot;Color&quot;, ColorRGBA.Blue&#41;;
geom.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;geom&#41;;</pre><p> Ta-daa!</p></div><h2><a
name="optional_mesh_features">Optional Mesh Features</a></h2><div
class="level2"><p> There are more vertex buffers in a Mesh than the three shown above. For an overview, see also <a
href="/com/jme3/gde/core/docs/jme3/advanced/meshes_and_models.html">Meshes and Models</a>.</p></div><h3><a
name="examplevertex_colors">Example: Vertex Colors</a></h3><div
class="level3"><p> Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient.</p><p> We will use the same mesh <code>m</code> as defined above, but with a special VertexColor material.</p><pre>Geometry coloredMesh = new Geometry &#40;&quot;ColoredMesh&quot;, m&#41;;
Material matVC = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/VertexColor.j3md&quot;&#41;;</pre><p> We create a float array color buffer.</p><ul><li
class="level1"><div
class="li"> We assign 4 color values, RGBA, to each vertex.</div><ul><li
class="level2"><div
class="li"> To loop over the 4 color values, we use a color index<pre>int colorIndex = 0;</pre></div></li></ul></li><li
class="level1"><div
class="li"> The color buffer contains four color values for each vertex.</div><ul><li
class="level2"><div
class="li"> The Quad in this example has 4 vertices.<pre>float&#91;&#93; colorArray = new float&#91;4*4&#93;;</pre></div></li><li
class="level2"><div
class="li"> Tip: If your mesh has a different number of vertices, you would write:<pre>float&#91;&#93; colorArray = new float&#91;yourVertexCount * 4&#93;</pre></div></li></ul></li></ul><p> We loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. Note that the values we use here are arbitrarily chosen! It&#039;s just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you&#039;d assign values for the color buffer depending on which color you want your mesh to have.</p><pre>for&#40;int i = 0; i &lt; 4; i++&#41;&#123;
rootNode.attachChild&#40;geom&#41;;</pre>
<p>
Ta-daa!
</p>
</div>
<h2><a>Optional Mesh Features</a></h2>
<div>
<p>
There are more vertex buffers in a Mesh than the three shown above. For an overview, see also <a href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">mesh</a>.
</p>
</div>
<h3><a>Example: Vertex Colors</a></h3>
<div>
<p>
Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient.
We will use the same mesh <code>m</code> as defined above, but with a special VertexColor material.
</p>
<pre>Geometry coloredMesh = new Geometry &#40;&quot;ColoredMesh&quot;, m&#41;;
Material matVC = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/VertexColor.j3md&quot;&#41;;</pre>
<p>
We create a float array color buffer.
</p>
<ul>
<li><div> We assign 4 color values, RGBA, to each vertex.</div>
<ul>
<li><div> To loop over the 4 color values, we use a color index <pre>int colorIndex = 0;</pre>
</div>
</li>
</ul>
</li>
<li><div> The color buffer contains four color values for each vertex.</div>
<ul>
<li><div> The Quad in this example has 4 vertices. <pre>float&#91;&#93; colorArray = new float&#91;4*4&#93;;</pre>
</div>
</li>
<li><div> Tip: If your mesh has a different number of vertices, you would write: <pre>float&#91;&#93; colorArray = new float&#91;yourVertexCount * 4&#93;</pre>
</div>
</li>
</ul>
</li>
</ul>
<p>
We loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. Note that the values we use here are arbitrarily chosen! It&#039;s just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you&#039;d assign values for the color buffer depending on which color you want your mesh to have.
</p>
<pre>for&#40;int i = 0; i &lt; 4; i++&#41;&#123;
// Red value (is increased by .2 on each next vertex here)
colorArray&#91;colorIndex++&#93;= 0.1f+&#40;.2f*i&#41;;
// Green value (is reduced by .2 on each next vertex)
@ -80,10 +205,32 @@ class="li"> Tip: If your mesh has a different number of vertices, you would writ
colorArray&#91;colorIndex++&#93;= 0.5f;
// Alpha value (no transparency set here)
colorArray&#91;colorIndex++&#93;= 1.0f;
&#125;</pre><p> Next, set the color buffer. An RGBA color value contains four float components, thus the parameter <code>4</code>.</p><pre>m.setBuffer&#40;Type.Color, 4, colorArray&#41;;
coloredMesh.setMaterial&#40;matVC&#41;;</pre><p> Now you see a gradient color extending from each vertex.</p></div><h3><a
name="examplepoint_mode">Example: Point Mode</a></h3><div
class="level3"><p> Alternatively, you can show the vertices as colored points instead of coloring the faces.</p><pre>Geometry coloredMesh = new Geometry &#40;&quot;ColoredMesh&quot;, cMesh&#41;;
&#125;</pre>
<p>
Next, set the color buffer. An RGBA color value contains four float components, thus the parameter <code>4</code>.
</p>
<pre>m.setBuffer&#40;Type.Color, 4, colorArray&#41;;
coloredMesh.setMaterial&#40;matVC&#41;;</pre>
<p>
Now you see a gradient color extending from each vertex.
</p>
</div>
<h3><a>Example: Point Mode</a></h3>
<div>
<p>
Alternatively, you can show the vertices as colored points instead of coloring the faces.
</p>
<pre>Geometry coloredMesh = new Geometry &#40;&quot;ColoredMesh&quot;, cMesh&#41;;
...
m.setMode&#40;Mesh.Mode.Points&#41;;
m.setPointSize&#40;10f&#41;;
@ -92,12 +239,32 @@ m.setStatic&#40;&#41;;
Geometry points = new Geometry&#40;&quot;Points&quot;, m&#41;;
points.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;points&#41;;
&nbsp;
rootNode.attachChild&#40;coloredMesh&#41;;</pre><p> This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad&#039;s faces are not rendered at all. This can be used for a special debugging or editing mode.</p></div><h2><a
name="tipfront_and_back_faces">Tip: Front and Back Faces</a></h2><div
class="level2"><p> By default, jME3 optimizes a scene by culling all backfaces. It determines which side the front or backface of a mesh is by the order of the vertices. The frontface is the one where the vertices are specified counter-clockwise.</p><p> This means your mesh, as created above, is invisible when seen from &quot;behind&quot;. This may not be a problem and is often even intended. If you use the custom meshes to form a polyhedron, or flat wallpaper-like object, rendering the backfaces (the inside of the polyhedron) would indeed be a waste of resources.</p><p> In case that your use case requires the backfaces to be visible, you have two options:</p><ul><li
class="level1"><div
class="li"> If you have a very simple scene, you can just deactivate backface culling for this one mesh&#039;s material. <br/> <code>mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off));</code></div></li><li
class="level1"><div
class="li"> The recommended solution is to specify each triangle twice, the second time with the opposite order of vertices. The second, reversed triangle makes up the backface. <br/> <code>int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 }; </code></div></li></ul></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_meshes?do=export_xhtmlbody">view online version</a></em></p>
rootNode.attachChild&#40;coloredMesh&#41;;</pre>
<p>
This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad&#039;s faces are not rendered at all. This can be used for a special debugging or editing mode.
</p>
</div>
<h2><a>Tip: Front and Back Faces</a></h2>
<div>
<p>
By default, jME3 optimizes a scene by culling all backfaces. It determines which side the front or backface of a mesh is by the order of the vertices. The frontface is the one where the vertices are specified counter-clockwise.
This means your mesh, as created above, is invisible when seen from &quot;behind&quot;. This may not be a problem and is often even intended. If you use the custom meshes to form a polyhedron, or flat wallpaper-like object, rendering the backfaces (the inside of the polyhedron) would indeed be a waste of resources.
In case that your use case requires the backfaces to be visible, you have two options:
</p>
<ul>
<li><div> If you have a very simple scene, you can just deactivate backface culling for this one mesh&#039;s material. <br/>
<code>mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off));</code></div>
</li>
<li><div> The recommended solution is to specify each triangle twice, the second time with the opposite order of vertices. The second, reversed triangle makes up the backface. <br/>
<code>int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 }; </code></div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_meshes?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 38 KiB

@ -1,12 +1,43 @@
<h1><a
name="debugging">Debugging</a></h1><div
class="level1"><p> When you deal with complex game engine features like animations or physics it is handy to get feedback from the engine how it interpreted the current state. Is the physical object&#039;s collision shape really where you think it is? Is the skeleton of the animated character moveing like you think it should? This document shows you how to activate visual debug aides.</p><p> What if you just want to quickly write code that loads models and brings them in their start position? You may not want to hunt for a sample model, convert it, add lights, and load materials. Instead you use &quot;hasslefree&quot; simple shapes a wireframe material: No model, no light source, no materials are needed to see them in the scene.</p><p> If you ever have problems with objects appearing in the wrong spot, with the wrong scale, or wrong orientation, simply attach debug shapes to your scene to have a point of reference in 3D space – just like a giant ruler. If your code positions the debug shapes correctly, but models remain invisible when you apply the same code to them, you know that the problem must be the model or the light or its material – and not the positioning code.</p><p> Here are some different debug shapes:</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:debug-shapes.png?id=jme3%3Aadvanced%3Adebugging"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png?w=600&amp;h=220" class="mediacenter" alt="" width="600" height="220" /></a></p></div><h2><a
name="debug_shapes">Debug Shapes</a></h2><div
class="level2"></div><h3><a
name="coordinate_axes">Coordinate Axes</a></h3><div
class="level3"><p> The coordinate axes (com.jme3.scene.debug.Arrow) help you see the cardinal directions (X,Y,Z) from their center point. Scale the arrows to use them as a &quot;ruler&quot; for a certain length.</p><pre>private void attachCoordinateAxes&#40;Vector3f pos&#41;&#123;
<h1><a>Debugging</a></h1>
<div>
<p>
When you deal with complex game engine features like animations or physics it is handy to get feedback from the engine how it interpreted the current state. Is the physical object&#039;s collision shape really where you think it is? Is the skeleton of the animated character moveing like you think it should? This document shows you how to activate visual debug aides.
</p>
<p>
What if you just want to quickly write code that loads models and brings them in their start position? You may not want to hunt for a sample model, convert it, add lights, and load materials. Instead you use &quot;hasslefree&quot; simple shapes a wireframe material: No model, no light source, no materials are needed to see them in the scene.
</p>
<p>
If you ever have problems with objects appearing in the wrong spot, with the wrong scale, or wrong orientation, simply attach debug shapes to your scene to have a point of reference in 3D space – just like a giant ruler. If your code positions the debug shapes correctly, but models remain invisible when you apply the same code to them, you know that the problem must be the model or the light or its material – and not the positioning code.
</p>
<p>
Here are some different debug shapes:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/debug-shapes.png">
</p>
</div>
<h2><a>Debug Shapes</a></h2>
<div>
</div>
<h3><a>Coordinate Axes</a></h3>
<div>
<p>
The coordinate axes (com.jme3.scene.debug.Arrow) help you see the cardinal directions (X,Y,Z) from their center point. Scale the arrows to use them as a &quot;ruler&quot; for a certain length.
</p>
<pre>private void attachCoordinateAxes&#40;Vector3f pos&#41;&#123;
Arrow arrow = new Arrow&#40;Vector3f.UNIT_X&#41;;
arrow.setLineWidth&#40;4&#41;; // make arrow thicker
putShape&#40;arrow, ColorRGBA.Red&#41;.setLocalTranslation&#40;pos&#41;;
@ -28,9 +59,18 @@ private Geometry putShape&#40;Mesh shape, ColorRGBA color&#41;&#123;
g.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;g&#41;;
return g;
&#125;</pre></div><h3><a
name="wireframe_grid">Wireframe Grid</a></h3><div
class="level3"><p> Use a wireframe grid (com.jme3.scene.debug.Grid) as a ruler or simple floor.</p><pre>private void attachGrid&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
&#125;</pre>
</div>
<h3><a>Wireframe Grid</a></h3>
<div>
<p>
Use a wireframe grid (com.jme3.scene.debug.Grid) as a ruler or simple floor.
</p>
<pre>private void attachGrid&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
Geometry g = new Geometry&#40;&quot;wireframe grid&quot;, new Grid&#40;size, size, 0.2f&#41; &#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.getAdditionalRenderState&#40;&#41;.setWireframe&#40;true&#41;;
@ -39,9 +79,18 @@ class="level3"><p> Use a wireframe grid (com.jme3.scene.debug.Grid) as a ruler o
g.center&#40;&#41;.move&#40;pos&#41;;
rootNode.attachChild&#40;g&#41;;
return g;
&#125;</pre></div><h3><a
name="wireframe_cube">Wireframe Cube</a></h3><div
class="level3"><p> Use a wireframe cube (com.jme3.scene.debug.WireBox) as a stand-in object to see whether your code scales, positions, or orients, loaded models right.</p><pre>public void attachWireBox&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
&#125;</pre>
</div>
<h3><a>Wireframe Cube</a></h3>
<div>
<p>
Use a wireframe cube (com.jme3.scene.debug.WireBox) as a stand-in object to see whether your code scales, positions, or orients, loaded models right.
</p>
<pre>public void attachWireBox&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
Geometry g = new Geometry&#40;&quot;wireframe cube&quot;, new WireBox&#40;size, size, size&#41;&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.getAdditionalRenderState&#40;&#41;.setWireframe&#40;true&#41;;
@ -50,9 +99,18 @@ class="level3"><p> Use a wireframe cube (com.jme3.scene.debug.WireBox) as a stan
g.setLocalTranslation&#40;pos&#41;;
rootNode.attachChild&#40;g&#41;;
return g;
&#125;</pre></div><h3><a
name="wireframe_sphere">Wireframe Sphere</a></h3><div
class="level3"><p> Use a wireframe sphere (com.jme3.scene.debug.WireSphere) as a stand-in object to see whether your code scales, positions, or orients, loaded models right.</p><pre>private void attachWireSphere&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
&#125;</pre>
</div>
<h3><a>Wireframe Sphere</a></h3>
<div>
<p>
Use a wireframe sphere (com.jme3.scene.debug.WireSphere) as a stand-in object to see whether your code scales, positions, or orients, loaded models right.
</p>
<pre>private void attachWireSphere&#40;Vector3f pos, float size, ColorRGBA color&#41;&#123;
Geometry g = new Geometry&#40;&quot;wireframe sphere&quot;, new WireSphere&#40;size&#41;&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.getAdditionalRenderState&#40;&#41;.setWireframe&#40;true&#41;;
@ -61,24 +119,56 @@ class="level3"><p> Use a wireframe sphere (com.jme3.scene.debug.WireSphere) as a
g.setLocalTranslation&#40;pos&#41;;
rootNode.attachChild&#40;g&#41;;
return g;
&#125;</pre></div><h2><a
name="wireframe_for_physics">Wireframe for Physics</a></h2><div
class="level2"><p> You can display a wireframe of the (usually invisible) collision shape around all physical objects. Use this for debugging when analyzing unexpected behaviour. Does not work with DETACHED physics, please switch to PARALLEL or SEQUENTIAL for debugging.</p><pre>physicsSpace.enableDebug&#40;assetManager&#41;;</pre></div><h2><a
name="wireframe_for_animations">Wireframe for Animations</a></h2><div
class="level2"><p> Making the skeleton visible inside animated models can be handy for debugging animations. The <code>control</code> object is an AnimControl, <code>player</code> is the loaded model.</p><pre> SkeletonDebugger skeletonDebug =
&#125;</pre>
</div>
<h2><a>Wireframe for Physics</a></h2>
<div>
<p>
You can display a wireframe of the (usually invisible) collision shape around all physical objects. Use this for debugging when analyzing unexpected behaviour. Does not work with DETACHED physics, please switch to PARALLEL or SEQUENTIAL for debugging.
</p>
<pre>physicsSpace.enableDebug&#40;assetManager&#41;;</pre>
</div>
<h2><a>Wireframe for Animations</a></h2>
<div>
<p>
Making the skeleton visible inside animated models can be handy for debugging animations. The <code>control</code> object is an AnimControl, <code>player</code> is the loaded model.
</p>
<pre> SkeletonDebugger skeletonDebug =
new SkeletonDebugger&#40;&quot;skeleton&quot;, control.getSkeleton&#40;&#41;&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.setColor&#40;&quot;Color&quot;, ColorRGBA.Green&#41;;
mat.getAdditionalRenderState&#40;&#41;.setDepthTest&#40;false&#41;;
skeletonDebug.setMaterial&#40;mat&#41;;
player.attachChild&#40;skeletonDebug&#41;;</pre></div><h2><a
name="exampletoggle_wireframe_on_model">Example: Toggle Wireframe on Model</a></h2><div
class="level2"><p> We assume that you have loaded a model with a material <code>mat</code>.</p><p> Then you can add a switch to toggle the model&#039;s wireframe on and off, like this:</p><ol><li
class="level1"><div
class="li"> Create a key input trigger that switches between the two materials: E.g. we toggle when the T key is pressed:<pre> inputManager.addMapping&#40;&quot;toggle wireframe&quot;, new KeyTrigger&#40;KeyInput.KEY_T&#41;&#41;;
inputManager.addListener&#40;actionListener, &quot;toggle wireframe&quot;&#41;;</pre></div></li><li
class="level1"><div
class="li"> Now add the toggle action to the action listener<pre> private ActionListener&#40;&#41; &#123;
player.attachChild&#40;skeletonDebug&#41;;</pre>
</div>
<h2><a>Example: Toggle Wireframe on Model</a></h2>
<div>
<p>
We assume that you have loaded a model with a material <code>mat</code>.
</p>
<p>
Then you can add a switch to toggle the model&#039;s wireframe on and off, like this:
</p>
<ol>
<li><div> Create a key input trigger that switches between the two materials: E.g. we toggle when the T key is pressed: <pre> inputManager.addMapping&#40;&quot;toggle wireframe&quot;, new KeyTrigger&#40;KeyInput.KEY_T&#41;&#41;;
inputManager.addListener&#40;actionListener, &quot;toggle wireframe&quot;&#41;;</pre>
</div>
</li>
<li><div> Now add the toggle action to the action listener <pre> private ActionListener&#40;&#41; &#123;
@Override
public void onAction&#40;String name, boolean pressed, float tpf&#41; &#123;
// toggle wireframe
@ -88,5 +178,10 @@ class="li"> Now add the toggle action to the action listener<pre> private Actio
&#125;
// else ... other input tests.
&#125;
&#125;;</pre></div></li></ol></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:debugging?do=export_xhtmlbody">view online version</a></em></p>
&#125;;</pre>
</div>
</li>
</ol>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:debugging?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 29 KiB

@ -1,92 +1,198 @@
<h1><a
name="jme3_effects_--_overview">jME3 Effects -- Overview</a></h1><div
class="level1"><p> <br/></p><p> jME3 supports various post-rendering and particle effects. This list contains screenshots and sample code that demonstrates how to add the effect to a scene.</p><p> <br/></p></div><h2><a
name="d_filter_effects">2D Filter Effects</a></h2><div
class="level2"></div><h3><a
name="screen_space_ambient_occlusion">Screen Space Ambient Occlusion</a></h3><div
class="level3"><p> <a
href="/wiki/lib/exe/fetch.php?hash=500208&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F08%2Fssao-article.png"><img
src="/wiki/lib/exe/fetch.php?hash=500208&amp;w=150&amp;h=100&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F08%2Fssao-article.png" class="mediaright" align="right" alt="" width="150" height="100" /></a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO.java">jme3/src/test/jme3test/post/TestSSAO.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO2.java">jme3/src/test/jme3test/post/TestSSAO2.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java">jme3/src/test/jme3test/post/TestTransparentSSAO.java</a></p><p> <a
href="http://jmonkeyengine.org/2010/08/16/screen-space-ambient-occlusion-for-jmonkeyengine-3-0/#more-321">Screen Space Ambient Occlusion for jMonkeyEngine</a> (article)</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:light-scattering-filter.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p></div><h3><a
name="light_scattering">Light Scattering</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestLightScattering.java">jme3/src/test/jme3test/post/TestLightScattering.java</a></p></div><h3><a
name="bloom">Bloom</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestBloom.java">jme3/src/test/jme3test/post/TestBloom.java</a></p><p> <a
href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">Bloom and Glow</a></p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:toon-dino.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p></div><h3><a
name="toon_effect">Toon Effect</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestCartoonEdge.java">jme3/src/test/jme3test/post/TestCartoonEdge.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentCartoonEdge.java">jme3/src/test/jme3test/post/TestTransparentCartoonEdge.java</a></p></div><h3><a
name="depth_of_field_blur">Depth of Field Blur</a></h3><div
class="level3"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:dof-blur.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestDepthOfField.java">jme3/src/test/jme3test/post/TestDepthOfField.java</a></p></div><h3><a
name="fog">Fog</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestFog.java">jme3/src/test/jme3test/post/TestFog.java</a> (temporary workaround, will be deprecated)</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:light-sources.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-sources.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p></div><h2><a
name="lighting_and_shadows">Lighting and Shadows</a></h2><div
class="level2"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestSimpleLighting.java">jme3/src/test/jme3test/light/TestSimpleLighting.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestLightRadius.java">jme3/src/test/jme3test/light/TestLightRadius.java</a></p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:shadow.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/shadow.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestManyLights.java">jme3/src/test/jme3test/light/TestManyLights.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestShadow.java">jme3/src/test/jme3test/light/TestShadow.java</a></p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java">jme3/src/test/jme3test/light/TestPssmShadow.java</a> = Parallel-Split Shadow Mapping (PSSM)</p></div><h2><a
name="water">Water</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:water.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p><p> <a
href="/com/jme3/gde/core/docs/jme3/advanced/water.html">&quot;SeaMonkey&quot; water</a></p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestSceneWater.java">jme3/src/test/jme3test/water/TestSceneWater.java</a></div></li></ul><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestSimpleWater.java">jme3/src/test/jme3test/water/TestSimpleWater.java</a></div></li></ul><p> <a
href="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/#comment-609">Rendering Water as Post-Process Effect</a></p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:water-post.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWater.java">jme3/src/test/jme3test/water/TestPostWater.java</a></div></li></ul><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWaterLake.java">jme3/src/test/jme3test/water/TestPostWaterLake.java</a></div></li></ul><p> <br/></p><p> <br/></p></div><h2><a
name="special_effects">Special Effects</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:explosion-5.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a> <a
href="/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html">Particle Emitters</a></p></div><h3><a
name="particlesexplosions_fire">Particles: Explosions, Fire</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestExplosionEffect.java">jme3/src/test/jme3test/effect/TestExplosionEffect.java</a> – debris, flame, flash, shockwave, smoke, sparks</p><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestParticleEmitter.java">jme3/src/test/jme3test/effect/TestParticleEmitter.java</a></p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:particle.png?id=jme3%3Aadvanced%3Aeffects_overview"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/particle.png?w=150&amp;h=100" class="mediaright" align="right" alt="" width="150" height="100" /></a></p></div><h3><a
name="particlessmoke">Particles: Smoke</a></h3><div
class="level3"><p> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestMovingParticle.java">jme3/src/test/jme3test/effect/TestMovingParticle.java</a></p><p> Particles can have any texture, e.g. fog, leaves, meteors, snowflakes, mosquitos</p><hr
/><p> See also:</p><ul><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html">Particle Emitters</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">Bloom and Glow</a></div></li><li
class="level1"><div
class="li"> <a
href="http://www.smashingmagazine.com/2008/08/07/50-photoshop-tutorials-for-sky-and-space-effects/">http://www.smashingmagazine.com/2008/08/07/50-photoshop-tutorials-for-sky-and-space-effects/</a></div></li></ul></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:effects_overview?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>jME3 Effects -- Overview</a></h1>
<div>
<p>
jME3 supports various post-rendering and particle effects. This list contains screenshots and sample code that demonstrates how to add the effect to a scene.
</p>
</div>
<h2><a>2D Filter Effects</a></h2>
<div>
</div>
<h3><a>Screen Space Ambient Occlusion</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestSSAO.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestSSAO2.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestSSAO2.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentSSAO.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestTransparentSSAO.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2010/08/16/screen-space-ambient-occlusion-for-jmonkeyengine-3-0/#more-321"><param name="text" value="<html><u>Screen Space Ambient Occlusion for jMonkeyEngine</u></html>"><param name="textColor" value="blue"></object> (article)</div>
</li>
</ul>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-scattering-filter.png">
</p>
</div>
<h3><a>Light Scattering</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestLightScattering.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestLightScattering.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h3><a>Bloom</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestBloom.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestBloom.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">Bloom and Glow</a></div>
</li>
</ul>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/toon-dino.png">
</p>
</div>
<h3><a>Toon Effect</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestCartoonEdge.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestCartoonEdge.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestTransparentCartoonEdge.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestTransparentCartoonEdge.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h3><a>Fade in / Fade out</a></h3>
<div>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/fade.html">Fade</a></div>
</li>
</ul>
</div>
<h3><a>Depth of Field Blur</a></h3>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/dof-blur.png">
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestDepthOfField.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestDepthOfField.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h3><a>Fog</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestFog.java"><param name="text" value="<html><u>jme3/src/test/jme3test/post/TestFog.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Lighting and Shadows</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestSimpleLighting.java"><param name="text" value="<html><u>jme3/src/test/jme3test/light/TestSimpleLighting.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestLightRadius.java"><param name="text" value="<html><u>jme3/src/test/jme3test/light/TestLightRadius.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/shadow.png"><img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-sources.png">
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestManyLights.java"><param name="text" value="<html><u>jme3/src/test/jme3test/light/TestManyLights.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestShadow.java"><param name="text" value="<html><u>jme3/src/test/jme3test/light/TestShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java"><param name="text" value="<html><u>jme3/src/test/jme3test/light/TestPssmShadow.java</u></html>"><param name="textColor" value="blue"></object> = Parallel-Split Shadow Mapping (PSSM)</div>
</li>
</ul>
</div>
<h2><a>Water</a></h2>
<div>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/water.html">&quot;SeaMonkey&quot; water</a></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestSceneWater.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestSceneWater.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestSimpleWater.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestSimpleWater.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/#comment-609"><param name="text" value="<html><u>Rendering Water as Post-Process Effect</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post.png"><img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water.png">
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWater.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestPostWater.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWaterLake.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestPostWaterLake.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Special Effects</a></h2>
<div>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html">Particle Emitters</a></div>
</li>
</ul>
</div>
<h3><a>Particles: Explosions, Fire</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestExplosionEffect.java"><param name="text" value="<html><u>jme3/src/test/jme3test/effect/TestExplosionEffect.java</u></html>"><param name="textColor" value="blue"></object> – debris, flame, flash, shockwave, smoke, sparks</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestParticleEmitter.java"><param name="text" value="<html><u>jme3/src/test/jme3test/effect/TestParticleEmitter.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png"><img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/particle.png">
</p>
</div>
<h3><a>Particles: Smoke</a></h3>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/effect/TestMovingParticle.java"><param name="text" value="<html><u>jme3/src/test/jme3test/effect/TestMovingParticle.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> Particles can have any texture, e.g. fog, leaves, meteors, snowflakes, mosquitos</div>
</li>
</ul>
<hr />
<p>
See also:
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/particle_emitters.html">Particle Emitters</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">Bloom and Glow</a></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.smashingmagazine.com/2008/08/07/50-photoshop-tutorials-for-sky-and-space-effects/"><param name="text" value="<html><u>Photoshop Tutorial for Sky and space effects (article)</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:effects_overview?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,114 @@
<h1><a>Endless Terrain</a></h1>
<div>
<p>
TerrainGrid is an extension built on top of the TerraMonkey tools like TerrainQuad and HeightMap, that provides &quot;infinite&quot; Terrain paging routines. <br/>
Thanks to Gábor (@anthyon) and Brent (@sploreg) for this contribution!
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
The classes with source code can be found in the org.jme3.terrain.geomipmapping and org.jme3.terrain.heightmap packages. Also there are 3 tests prepared in the jme3test.terrain package:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/terrain/TerrainGridTest.java"><param name="text" value="<html><u>TerrainGridTest.java</u></html>"><param name="textColor" value="blue"></object>: uses an ImageBasedHeightMapGrid instance to load the tiles</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java"><param name="text" value="<html><u>TerrainFractalGridTest.java</u></html>"><param name="textColor" value="blue"></object>: makes use of the FractalHeightMapGrid class, and generates a terrain from noise</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/terrain/TerrainGridAlphaMapTest.java"><param name="text" value="<html><u>TerrainGridAlphaMapTest.java</u></html>"><param name="textColor" value="blue"></object>: shows how to use TerrainGridListener to change the material of the tiles</div>
</li>
</ul>
</div>
<h2><a>Specification</a></h2>
<div>
<p>
TerrainGrid is made up of the TerrainGrid class, and the HeightMapGrid and TerrainGridListener interfaces.
</p>
<ul>
<li><div> TerrainGrid is the central class of the system. It takes care for handling camera movement in LODUpdate, loading and unloading terrain tiles on demand, and notifying any registered listeners of changes.</div>
</li>
<li><div> TerrainGridListener defines two events to listen to:</div>
<ul>
<li><div> gridMoved(Vector3f): gets the new center as parameter after terrain update, so any objects can be added or removed as needed.</div>
</li>
<li><div> Material tileLoaded(Material material, Vector3f cell): notifies the system about a tile being loaded. Parameters are a cloned value of the material added to the TerrainGrid, and the cell of the new tile. The system can change the material according to this information (eg. load required alphamaps, etc).</div>
</li>
</ul>
</li>
</ul>
<p>
<br/>
Multiple listeners can be added to the TerrainGrid, they will be called in the order of addition, so it’s possible to have multiple changes to the material before completing the load of the tile.
<br/>
HeightMapGrid adds the possibility of loading terrain tiles on demand instead of having a simple height array. There’s no predefined way of how to store these tiles, it only takes care of loading one HeightMap object at given location at a time.
</p>
</div>
<h2><a>Motivation</a></h2>
<div>
<p>
After playing around with the terrain in jME3, soon comes the requirement of having larger explorable lands. Increasing the size of one TerrainQuad leads to more memory usage, while it will still be easy to reach the worlds boundaries. That’s why TerrainGrid was designed. It extends the TerraindQuad class and uses 4 HeightMaps (dark blue) as the four sub-quad. This means that a terrain of size 513 will use tiles of 257. Also an LRUCache is built into the terrain package, so surrounding tiles (green) can be pre-cached on a different thread, lowering the loading time. The quads are updated as the camera approaches the boundary of the light blue section.
</p>
</div>
<h2><a>Rationale</a></h2>
<div>
<p>
The design of the TerrainGrid system was chosen carefully, so that minimal effort needs to be taken to switch from previous TerrainQuad uses. It has the same constructors with the small exception that instead of an array of heightmap it takes a HeightMapGrid instance. All other parameters are forwarded down to the underlying TerrainQuad system.
There exist also two basic HeightMapGrid implementations:
</p>
<ul>
<li><div> ImageBasedHeightMapGrid: uses a sequentially numbered, 16 bit grayscale heightmaps. The physical filename of these files can be generated through the Namer interface. When a tile cannot be found by the assetManager, an empty (all-zero) heightmap is created, and a warning is added to the log.</div>
</li>
<li><div> FractalHeightMapGrid: uses a noise library to create a landscape on the fly. The shape of the terrain can be controlled by the various parameters and postfilters of the fractals. With the help of this grid implementation there’s no limitation – above of floating point precision limits – how far the camera can get. The tiles generated this way can be cached to the filesystem, for later modification. The FractalHeightMapGrid will always load from cache if a tile exists there!</div>
</li>
</ul>
</div>
<h2><a>Usage</a></h2>
<div>
<ol>
<li><div> instantiate a TerrainGrid object</div>
</li>
<li><div> set material, listeners, translation, scale, etc.</div>
</li>
<li><div> add a LODControl instance to the object</div>
</li>
<li><div> call initialize with the camera location</div>
</li>
<li><div> (optional) add it to the physicsSpace as you would a TerrainQuad</div>
</li>
</ol>
<p>
Further information about terrain and TerrainQuad can be found in the wiki at:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_terrain"><param name="text" value="<html><u>http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_terrain</u></html>"><param name="textColor" value="blue"></object> and</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:terrain"><param name="text" value="<html><u>http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:terrain</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:endless_terraingrid?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@ -0,0 +1,95 @@
<h1><a>jME3 Headless Server</a></h1>
<div>
<p>
When adding multiplayer to your game, you may find that your server needs to know about game state (e.g. where are players, objects? Was that a direct hit? etc.) You can code all this up yourself, but there&#039;s an easier way.
</p>
<p>
It&#039;s very easy to change your current (client) game to function as a server as well.
</p>
</div>
<h2><a>What Does Headless Mean?</a></h2>
<div>
<p>
A headless server…
</p>
<ul>
<li><div> does not display any output – no window opens, no audio plays, no graphics are rendered.</div>
</li>
<li><div> ignores all input – no input handling.</div>
</li>
<li><div> keeps game state – you can attach to, transform, and save the rootNode, although the scene is not displayed.</div>
</li>
<li><div> calls the <code>simpleUpdate()</code> loop – you can run tests and trigger events as usual.</div>
</li>
</ul>
</div>
<h2><a>Client Code</a></h2>
<div>
<p>
First, let&#039;s take a look at the default way of creating a new game (in its simplest form):
</p>
<pre>public static void main&#40;String&#91;&#93; args&#41; &#123;
Application app = new Main&#40;&#41;;
app.start&#40;&#41;;
&#125;</pre>
</div>
<h2><a>Headless Server Code</a></h2>
<div>
<p>
Now, with a simple change you can start your game in Headless mode. This means that all input and audio/visual output will be ignored. That&#039;s a good thing for a server.
</p>
<pre>import com.jme3.system.JmeContext;
import com.jme3.system.JmeContext.Type;
&nbsp;
public static void main&#40;String&#91;&#93; args&#41; &#123;
Application app = new Main&#40;&#41;;
app.start&#40;JmeContext.Type.Headless&#41;;
&#125;</pre>
</div>
<h2><a>Next steps</a></h2>
<div>
<p>
Okay, so you can now start your game in a headless &#039;server mode&#039;, where to go from here?
</p>
<ul>
<li><div> Parse <code>String[] args</code> from the <code>main</code>-method to enable server mode on demand (e.g. start your server like <code>java -jar mygame.jar –server</code>.</div>
</li>
<li><div> Integrate <a href="/com/jme3/gde/core/docs/jme3/advanced/networking.html">SpiderMonkey</a>, to provide game updates to the server over a network.</div>
</li>
<li><div> Only execute code that&#039;s needed. (E.g. place all rendering code inside an <code>if (servermode)</code>-block) (or <code>if (!servermode)</code> for the client).</div>
</li>
<li><div> Add decent <a href="/com/jme3/gde/core/docs/jme3/advanced/logging.html">logging</a> so your server actually makes sense.</div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:intermediate?do=showtag&amp;tag=tag%3Aintermediate">intermediate</a>,
<a href="/wiki/doku.php/tag:server?do=showtag&amp;tag=tag%3Aserver">server</a>,
<a href="/wiki/doku.php/tag:spidermonkey?do=showtag&amp;tag=tag%3Aspidermonkey">spidermonkey</a>,
<a href="/wiki/doku.php/tag:headless?do=showtag&amp;tag=tag%3Aheadless">headless</a>,
<a href="/wiki/doku.php/tag:network?do=showtag&amp;tag=tag%3Anetwork">network</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:headless_server?do=export_xhtmlbody">view online version</a></em></p>

@ -1,55 +1,143 @@
<h1><a
name="physical_hinges_and_joints">Physical Hinges and Joints</a></h1><div
class="level1"><p> The jMonkeyEngine3 has built-in support for <a
href="http://jbullet.advel.cz">jBullet physics</a> via the <code>com.jme3.bullet</code> package.</p><p> Game Physics are not only employed to calculate collisions, but they can also simulate hinges and joints. Think of pulley chains, shaky rope bridges, swinging pendulums, or (trap)door and chest hinges. Physics are a great addition to e.g. an action or puzzle game.</p><p> In this example, we will create a pendulum. The joint is the (invisible) connection between the pendulum body and the hook. You will see that you can use what you learn from the simple pendulum and apply it to other joint/hinge objects (rope bridges, etc).</p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsHingeJoint.java">TestPhysicsHingeJoint.java</a></div></li></ul></div><h2><a
name="overview_of_this_physics_application">Overview of this Physics Application</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Create a SimpleApplication with a <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a></div><ul><li
class="level2"><div
class="li"> This gives us a PhysicsSpace for PhysicsControls</div></li></ul></li><li
class="level1"><div
class="li"> For the pendulum, we use a Spatial with a PhysicsControl, and we apply physical forces to them.</div><ul><li
class="level2"><div
class="li"> The parts of the &quot;pendulum&quot; are Physics Control&#039;ed Spatials with Collision Shapes.</div></li><li
class="level2"><div
class="li"> We create a fixed <code>hookNode</code> and a dynamic <code>pendulumNode</code>.</div></li></ul></li><li
class="level1"><div
class="li"> We can &quot;crank the handle&quot; and rotate the joint like a hinge, or we can let loose and expose the joints freely to gravity.</div><ul><li
class="level2"><div
class="li"> For physical forces we will use the method <code>joint.enableMotor();</code></div></li></ul></li></ol></div><h2><a
name="creating_a_fixed_node">Creating a Fixed Node</a></h2><div
class="level2"><p> The hookNode is the fixed point from which the pendulum hangs. It has no mass.</p><pre>Node hookNode=PhysicsTestHelper.createPhysicsTestNode&#40;assetManager, new BoxCollisionShape&#40;new Vector3f&#40; .1f, .1f, .1f&#41;&#41;,0&#41;;
<h1><a>Physical Hinges and Joints</a></h1>
<div>
<p>
The jMonkeyEngine3 has built-in support for <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jbullet.advel.cz"><param name="text" value="<html><u>jBullet physics</u></html>"><param name="textColor" value="blue"></object> via the <code>com.jme3.bullet</code> package.
</p>
<p>
Game Physics are not only employed to calculate collisions, but they can also simulate hinges and joints. Think of pulley chains, shaky rope bridges, swinging pendulums, or (trap)door and chest hinges. Physics are a great addition to e.g. an action or puzzle game.
</p>
<p>
In this example, we will create a pendulum. The joint is the (invisible) connection between the pendulum body and the hook. You will see that you can use what you learn from the simple pendulum and apply it to other joint/hinge objects (rope bridges, etc).
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsHingeJoint.java"><param name="text" value="<html><u>TestPhysicsHingeJoint.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Overview of this Physics Application</a></h2>
<div>
<ol>
<li><div> Create a SimpleApplication with a <a href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a> </div>
<ul>
<li><div> This gives us a PhysicsSpace for PhysicsControls</div>
</li>
</ul>
</li>
<li><div> For the pendulum, we use a Spatial with a PhysicsControl, and we apply physical forces to them.</div>
<ul>
<li><div> The parts of the &quot;pendulum&quot; are Physics Control&#039;ed Spatials with Collision Shapes. </div>
</li>
<li><div> We create a fixed <code>hookNode</code> and a dynamic <code>pendulumNode</code>. </div>
</li>
</ul>
</li>
<li><div> We can &quot;crank the handle&quot; and rotate the joint like a hinge, or we can let loose and expose the joints freely to gravity. </div>
<ul>
<li><div> For physical forces we will use the method <code>joint.enableMotor();</code></div>
</li>
</ul>
</li>
</ol>
</div>
<h2><a>Creating a Fixed Node</a></h2>
<div>
<p>
The hookNode is the fixed point from which the pendulum hangs. It has no mass.
</p>
<pre>Node hookNode=PhysicsTestHelper.createPhysicsTestNode&#40;
assetManager, new BoxCollisionShape&#40;new Vector3f&#40; .1f, .1f, .1f&#41;&#41;,0&#41;;
hookNode.getControl&#40;RigidBodyControl.class&#41;.setPhysicsLocation&#40;new Vector3f&#40;0f,0,0f&#41;&#41;;
&nbsp;
rootNode.attachChild&#40;hookNode&#41;;
getPhysicsSpace&#40;&#41;.add&#40;hookNode&#41;;</pre><p> For a rope bridge, there would be two fixed nodes where the bridge is attached to the mountainside.</p></div><h2><a
name="creating_a_dynamic_node">Creating a Dynamic Node</a></h2><div
class="level2"><p> The pendulumNode is the dynamic part of the construction. It has a mass.</p><pre>Node pendulumNode=PhysicsTestHelper.createPhysicsTestNode&#40;assetManager, new BoxCollisionShape&#40;new Vector3f&#40; .3f, .3f, .3f&#41;&#41;,1&#41;;
getPhysicsSpace&#40;&#41;.add&#40;hookNode&#41;;</pre>
<p>
For a rope bridge, there would be two fixed nodes where the bridge is attached to the mountainside.
</p>
</div>
<h2><a>Creating a Dynamic Node</a></h2>
<div>
<p>
The pendulumNode is the dynamic part of the construction. It has a mass.
</p>
<pre>Node pendulumNode=PhysicsTestHelper.createPhysicsTestNode&#40;
assetManager, new BoxCollisionShape&#40;new Vector3f&#40; .3f, .3f, .3f&#41;&#41;,1&#41;;
pendulumNode.getControl&#40;RigidBodyControl.class&#41;.setPhysicsLocation&#40;new Vector3f&#40;0f,-1,0f&#41;&#41;;
rootNode.attachChild&#40;pendulumNode&#41;;
getPhysicsSpace&#40;&#41;.add&#40;pendulumNode&#41;;</pre><p> For a rope bridge, each set of planks would be one dynamic node.</p></div><h2><a
name="understanding_dof_joints_and_hinges">Understanding DOF, Joints, and Hinges</a></h2><div
class="level2"><p> A PhysicsHingeJoint is an invisible connection between two nodes – here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the <em>mechanical degree of freedom</em> (DOF) of another object.</p><p> Consider a free falling, &quot;unchained&quot; object in physical 3D space: It has 6 DOFs:</p><ul><li
class="level1"><div
class="li"> It translates along 3 axes</div></li><li
class="level1"><div
class="li"> It rotates around 3 axes</div></li></ul><p> Now consider some examples of objects with joints:</p><ul><li
class="level1"><div
class="li"> An individual chain link is free to spin and move around, but joined into a chain, the link&#039;s movement is restricted to stay with the surrounding links.</div></li><li
class="level1"><div
class="li"> A person&#039;s arm can rotate around some axes, but not around others. The shoulder joint allows one and restricts the other.</div></li><li
class="level1"><div
class="li"> A door hinge is one of the most restricted types of joint: It can only rotate around one axis.</div></li></ul><p> You&#039;ll understand that, when creating any type of joint, it is important to correctly specify the DOFs that the joint restricts, and the DOFs that the joint allows. For the typical DOF of a <a
href="/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html">ragDoll</a> character&#039;s limbs, jME even offers a special joint, <code>PhysicsConeJoint</code>.</p></div><h2><a
name="creating_the_joint">Creating the Joint</a></h2><div
class="level2"><p> You create the PhysicsHingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the PhysicsHingeJoint constructor requires the two node objects. You also have to specify axes and pivots – they are the degrees of freedom that you just heard about.</p><pre>private HingeJoint joint;
getPhysicsSpace&#40;&#41;.add&#40;pendulumNode&#41;;</pre>
<p>
For a rope bridge, each set of planks would be one dynamic node.
</p>
</div>
<h2><a>Understanding DOF, Joints, and Hinges</a></h2>
<div>
<p>
A PhysicsHingeJoint is an invisible connection between two nodes – here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the <em>mechanical degree of freedom</em> (DOF) of another object.
</p>
<p>
Consider a free falling, &quot;unchained&quot; object in physical 3D space: It has 6 DOFs:
</p>
<ul>
<li><div> It translates along 3 axes</div>
</li>
<li><div> It rotates around 3 axes</div>
</li>
</ul>
<p>
Now consider some examples of objects with joints:
</p>
<ul>
<li><div> An individual chain link is free to spin and move around, but joined into a chain, the link&#039;s movement is restricted to stay with the surrounding links.</div>
</li>
<li><div> A person&#039;s arm can rotate around some axes, but not around others. The shoulder joint allows one and restricts the other.</div>
</li>
<li><div> A door hinge is one of the most restricted types of joint: It can only rotate around one axis. </div>
</li>
</ul>
<p>
You&#039;ll understand that, when creating any type of joint, it is important to correctly specify the DOFs that the joint restricts, and the DOFs that the joint allows. For the typical DOF of a <a href="/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html">ragDoll</a> character&#039;s limbs, jME even offers a special joint, <code>PhysicsConeJoint</code>.
</p>
</div>
<h2><a>Creating the Joint</a></h2>
<div>
<p>
You create the PhysicsHingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the PhysicsHingeJoint constructor requires the two node objects. You also have to specify axes and pivots – they are the degrees of freedom that you just heard about.
</p>
<pre>private HingeJoint joint;
...
public void simpleInitApp&#40;&#41; &#123;
...
@ -61,26 +149,76 @@ class="level2"><p> You create the PhysicsHingeJoint after you have created the n
new Vector3f&#40;0f, 0f, 0f&#41;, // pivot point of A
new Vector3f&#40;0f,-1f, 0f&#41;, // pivot point of B
Vector3f.UNIT_Z, // DoF Axis of A (Z axis)
Vector3f.UNIT_Z &#41;; // DoF Axis of B (Z axis)</pre><p> Specify the following parameters for each joint:</p><ul><li
class="level1"><div
class="li"> PhysicsControl A and B – the two nodes that are to be joined</div></li><li
class="level1"><div
class="li"> Vector3f pivot A and pivot B – coordinates of the two attachment points</div><ul><li
class="level2"><div
class="li"> The points typically lie on the surface of the PhysicsControl&#039;s Spatials, rarely in the middle.</div></li></ul></li><li
class="level1"><div
class="li"> Vector3f axisA and axisB – around which axes each node is allowed to spin.</div><ul><li
class="level2"><div
class="li"> In our example, we constrain the pendulum to swing only along the Z axis.</div></li></ul></li></ul><p> Remember to add all joint objects to the physicsSpace, just like you would do with any physical objects.</p><pre>bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;joint&#41;;</pre><p> <strong>Tip:</strong> If you want the joint to be visible, attach a geometry to the dynamic node, and translate it to its start position.</p></div><h2><a
name="apply_physical_forces">Apply Physical Forces</a></h2><div
class="level2"><p> You can apply forces to dynamic nodes (the ones that have a mass), and see how other joined (&quot;chained&quot;) objects are dragged along.</p><p> Alternatively, you can also apply forces to the joint itself. In a game, you may want to spin an automatic revolving door, or slam a door closed in a spooky way, or dramatically open the lid of a treasure chest.</p><p> The method to call on the joint is <code>enableMotor()</code>.</p><pre>joint.enableMotor&#40;true, 1, .1f&#41;;
joint.enableMotor&#40;true, -1, .1f&#41;;</pre><ol><li
class="level1"><div
class="li"> Switch the motor on by supplying <code>true</code></div></li><li
class="level1"><div
class="li"> Specify the velocity with which the joint should rotate around the specified axis.</div><ul><li
class="level2"><div
class="li"> Use positive and negative numbers to change direction.</div></li></ul></li><li
class="level1"><div
class="li"> Specify the impulse for this motor. Heavier masses need a bigger impulse to be moved.</div></li></ol><p> When you disable the motor, the chained nodes are exposed to gravity again:</p><pre>joint.enableMotor&#40;false, 0, 0&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:hinges_and_joints?do=export_xhtmlbody">view online version</a></em></p>
Vector3f.UNIT_Z &#41;; // DoF Axis of B (Z axis)</pre>
<p>
Specify the following parameters for each joint:
</p>
<ul>
<li><div> PhysicsControl A and B – the two nodes that are to be joined</div>
</li>
<li><div> Vector3f pivot A and pivot B – coordinates of the two attachment points</div>
<ul>
<li><div> The points typically lie on the surface of the PhysicsControl&#039;s Spatials, rarely in the middle.</div>
</li>
</ul>
</li>
<li><div> Vector3f axisA and axisB – around which axes each node is allowed to spin.</div>
<ul>
<li><div> In our example, we constrain the pendulum to swing only along the Z axis.</div>
</li>
</ul>
</li>
</ul>
<p>
Remember to add all joint objects to the physicsSpace, just like you would do with any physical objects.
</p>
<pre>bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;joint&#41;;</pre>
<p>
<strong>Tip:</strong> If you want the joint to be visible, attach a geometry to the dynamic node, and translate it to its start position.
</p>
</div>
<h2><a>Apply Physical Forces</a></h2>
<div>
<p>
You can apply forces to dynamic nodes (the ones that have a mass), and see how other joined (&quot;chained&quot;) objects are dragged along.
</p>
<p>
Alternatively, you can also apply forces to the joint itself. In a game, you may want to spin an automatic revolving door, or slam a door closed in a spooky way, or dramatically open the lid of a treasure chest.
</p>
<p>
The method to call on the joint is <code>enableMotor()</code>.
</p>
<pre>joint.enableMotor&#40;true, 1, .1f&#41;;
joint.enableMotor&#40;true, -1, .1f&#41;;</pre>
<ol>
<li><div> Switch the motor on by supplying <code>true</code></div>
</li>
<li><div> Specify the velocity with which the joint should rotate around the specified axis. </div>
<ul>
<li><div> Use positive and negative numbers to change direction.</div>
</li>
</ul>
</li>
<li><div> Specify the impulse for this motor. Heavier masses need a bigger impulse to be moved.</div>
</li>
</ol>
<p>
When you disable the motor, the chained nodes are exposed to gravity again:
</p>
<pre>joint.enableMotor&#40;false, 0, 0&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:hinges_and_joints?do=export_xhtmlbody">view online version</a></em></p>

@ -1,87 +1,202 @@
<h1><a
name="head-up_display_hud">Head-Up Display (HUD)</a></h1><div
class="level1"><p> A HUD (Head-Up Display) is part of a game&#039;s visual user interface. It&#039;s an overlay that displays additional information as (typically) 2-dimensional text or icons on the screen, on top of the 3D scene.</p><p> HUDs are used to supply players with essential information about the game state.</p><ul><li
class="level1"><div
class="li"> Status: Score, minimap, points, stealth mode, …</div></li><li
class="level1"><div
class="li"> Resources: Ammunition, lives/health, time, …</div></li><li
class="level1"><div
class="li"> Vehicle instruments: Cockpit, speedometer, …</div></li><li
class="level1"><div
class="li"> Navigational aides: Crosshairs, cursor, hand, …</div></li></ul><p> <a
href="/wiki/lib/exe/fetch.php?hash=c9f2a3&amp;media=http%3A%2F%2Fwww.jmonkeyengine.com%2Fwp-content%2Fuploads%2F2010%2F10%2Fgrapplinghook.jpg"><img
src="/wiki/lib/exe/fetch.php?hash=c9f2a3&amp;w=256&amp;h=192&amp;media=http%3A%2F%2Fwww.jmonkeyengine.com%2Fwp-content%2Fuploads%2F2010%2F10%2Fgrapplinghook.jpg" class="mediaright" align="right" title="www.jmonkeyengine.com_wp-content_uploads_2010_10_grapplinghook.jpg" alt="www.jmonkeyengine.com_wp-content_uploads_2010_10_grapplinghook.jpg" width="256" height="192" /></a></p><p> Not all games have, or need a HUD. To avoid breaking the immersion and cluttering the screen, only use a HUD if it is the only way to convey certain information.</p><p> You have two options how to create HUDs.</p><ul><li
class="level1"><div
class="li"> To create full-featured user interfaces, you use Nifty <acronym
title="Graphical User Interface">GUI</acronym>. (Recommended)</div></li><li
class="level1"><div
class="li"> If you just quickly want to display a line of text or an icon, you use the guiNode.</div></li></ul></div><h2><a
name="hud_with_nifty_gui">HUD with Nifty GUI</a></h2><div
class="level2"><p> The recommended approach to create HUDs is using Nifty <acronym
title="Graphical User Interface">GUI</acronym>.</p><ol><li
class="level1"><div
class="li"> Lay out the <acronym
title="Graphical User Interface">GUI</acronym> in one or several Nifty <acronym
title="Extensible Markup Language">XML</acronym> files.</div></li><li
class="level1"><div
class="li"> Write the controller classes in Java.</div></li><li
class="level1"><div
class="li"> Load the <acronym
title="Extensible Markup Language">XML</acronym> file with the controller object in your game&#039;s simpleInit() method.</div></li></ol><p> The advantage of Nifty <acronym
title="Graphical User Interface">GUI</acronym> is that it is well integrated into jME and the jMonkeyPlatform, and that it offers all the features that you expect from a professional modern user interface. The only small disadvantage is that you (currently still) have to lay out the interface in <acronym
title="Extensible Markup Language">XML</acronym>. You can see this as an advantage too, as it enables you to edit the user interface without editing the code afterwards.</p><p> For HUDs, you Basically follow the same instructions as for creating a normal <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a>, you just don&#039;t pause the game while the HUD is up.</p></div><h2><a
name="the_gui_node">The GUI Node</a></h2><div
class="level2"><p> Using the <acronym
title="Graphical User Interface">GUI</acronym> Node is the default approach in jme3 to create very simple, static HUDs. If you just quickly want to display a line of text, or a simple icon on the screen, use this no-frills method. If you want a more advanced HUD with effects and interaction, use <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a>.</p><p> Next to the rootNode for the 3-dimensional scene graph, jME3 also offers a 2-dimension (orthogonal) node, the <code>guiNode</code>. This is how you use it for HUDs:</p><ul><li
class="level1"><div
class="li"> Create a <acronym
title="Graphical User Interface">GUI</acronym> element (text or image).</div></li><li
class="level1"><div
class="li"> Attach the <acronym
title="Graphical User Interface">GUI</acronym> element to the guiNode.</div></li><li
class="level1"><div
class="li"> Place the <acronym
title="Graphical User Interface">GUI</acronym> element in the orthogonal render queue using <code>setQueueBucket(Bucket.Gui)</code>.</div></li></ul><p> The element appears as 2-D, static element on the screen.</p><p> By default, the guiNode has some scene graph statistics attached in SimpleApplication. To clear the guiNode and attach your own <acronym
title="Graphical User Interface">GUI</acronym> elements, you detach all children.</p><pre>guiNode.detachAllChildren&#40;&#41;;</pre></div><h3><a
name="displaying_pictures_in_the_hud">Displaying Pictures in the HUD</a></h3><div
class="level3"><p> A simple image can be displayed using <code>com.jme3.ui.Picture</code>.</p><pre>Picture pic = new Picture&#40;&quot;HUD Picture&quot;&#41;;
<h1><a>Head-Up Display (HUD)</a></h1>
<div>
<p>
<img src="/wiki/lib/exe/fetch.php">
</p>
<p>
A HUD (Head-Up Display) is part of a game&#039;s visual user interface. It&#039;s an overlay that displays additional information as (typically) 2-dimensional text or icons on the screen, on top of the 3D scene. Not all games have, or need a HUD. To avoid breaking the immersion and cluttering the screen, only use a HUD if it is the only way to convey certain information.
</p>
<p>
HUDs are used to supply players with essential information about the game state.
</p>
<ul>
<li><div> Status: Score, minimap, points, stealth mode, …</div>
</li>
<li><div> Resources: Ammunition, lives/health, time, …</div>
</li>
<li><div> Vehicle instruments: Cockpit, speedometer, …</div>
</li>
<li><div> Navigational aides: Crosshairs, mouse pointer or hand, …</div>
</li>
</ul>
<p>
You have two options how to create HUDs.
</p>
<div><table>
<tr>
<th>Option</th><th>Pros</th><th>Cons</th>
</tr>
<tr>
<th>Attach elements to default guiNode:</th><td>Easy to learn. jMonkeyEngine built-in <acronym title="Application Programming Interface">API</acronym> for attaching images and bitmap text.</td><td>Only basic features. <br/>
You will have to write custom controls / buttons / effects if you need them.</td>
</tr>
<tr>
<th>Use advanced <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> integration:</th><td>Full-featured interactive user interface. <br/>
Includes buttons, effects, controls. <br/>
Supports <acronym title="Extensible Markup Language">XML</acronym> and Java layouts.</td><td>Steeper learning curve.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [834-1253] -->
</div>
<h2><a>Simple HUD: GUI Node</a></h2>
<div>
<p>
Using the <acronym title="Graphical User Interface">GUI</acronym> Node is the default approach in jme3 to create simple HUDs. If you just quickly want to display a line of text, or a simple icon on the screen, use this no-frills method.
</p>
<p>
Next to the rootNode for the 3-dimensional scene graph, jME3 also offers a 2-dimension (orthogonal) node, the <code>guiNode</code>.
</p>
<p>
This is how you use the guiNode for HUDs:
</p>
<ul>
<li><div> Create a <acronym title="Graphical User Interface">GUI</acronym> element: BitmapText or Picture.</div>
</li>
<li><div> Attach the element to the guiNode. </div>
</li>
<li><div> Place the element in the orthogonal render queue using <code>setQueueBucket(Bucket.Gui)</code>. </div>
</li>
</ul>
<p>
The BitmapTexts and Pictures appear as 2 dimensional element on the screen.
</p>
<p>
<strong>Note:</strong> The size unit for the guiNode is pixels, not world units.
</p>
<p>
By default, the guiNode has some scene graph statistics attached in SimpleApplication. To clear the guiNode and attach your own <acronym title="Graphical User Interface">GUI</acronym> elements, you detach all children.
</p>
<pre>guiNode.detachAllChildren&#40;&#41;;</pre>
</div>
<h3><a>Displaying Pictures in the HUD</a></h3>
<div>
<p>
A simple image can be displayed using <code>com.jme3.ui.Picture</code>.
</p>
<pre>Picture pic = new Picture&#40;&quot;HUD Picture&quot;&#41;;
pic.setImage&#40;assetManager, &quot;Textures/ColoredTex/Monkey.png&quot;, true&#41;;
pic.setWidth&#40;settings.getWidth&#40;&#41;/2&#41;;
pic.setHeight&#40;settings.getHeight&#40;&#41;/2&#41;;
pic.setPosition&#40;settings.getWidth&#40;&#41;/4, settings.getHeight&#40;&#41;/4&#41;;
guiNode.attachChild&#40;pic&#41;;</pre><p> When you set the last boolean in setImage() to true, the alpha channel of your image will be rendered transparent/translucent.</p></div><h3><a
name="displaying_text_in_the_hud">Displaying Text in the HUD</a></h3><div
class="level3"><p> You use <code>com.jme3.font.BitmapText</code> to display text on the screen.</p><pre>BitmapText hudText = new BitmapText&#40;guiFont, false&#41;;
guiNode.attachChild&#40;pic&#41;;</pre>
<p>
When you set the last boolean in setImage() to true, the alpha channel of your image is rendered transparent/translucent.
</p>
</div>
<h3><a>Displaying Text in the HUD</a></h3>
<div>
<p>
You use <code>com.jme3.font.BitmapText</code> to display text on the screen.
</p>
<pre>BitmapText hudText = new BitmapText&#40;guiFont, false&#41;;
hudText.setSize&#40;guiFont.getCharSet&#40;&#41;.getRenderedSize&#40;&#41;&#41;; // font size
hudText.setColor&#40;ColorRGBA.Blue&#41;; // font color
hudText.setText&#40;&quot;You can write any string here&quot;&#41;; // the text
hudText.setLocalTranslation&#40;300, hudText.getLineHeight&#40;&#41;, 0&#41;; // position
guiNode.attachChild&#40;hudText&#41;;</pre><p> The BitmapFont object <code>guiFont</code> is a default font provided by SimpleApplication. Copy you own fonts as .fnt+.png files into the <code>assets/Interface/Fonts</code> directory and load them like this:</p><pre>BitmapFont myFont = assetManager.loadFont(&quot;Interface/Fonts/Console.fnt&quot;);
hudText = new BitmapText(myFont, false);</pre></div><h3><a
name="displaying_geometries_in_the_hud">Displaying Geometries in the HUD</a></h3><div
class="level3"><p> It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static <acronym
title="Graphical User Interface">GUI</acronym> elements. Note that if you use a lit Material, you must add a light to the guiNode. Also remember that size units are pixels in the HUD (a 2-wu cube is displayed 2 pixels wide).</p></div><h3><a
name="positioning_hud_elements">Positioning HUD Elements</a></h3><div
class="level3"><ul><li
class="level1"><div
class="li"> When positioning text and images in 2D, the bottom left corner of the screen is <code>(0f,0f)</code>, and the top right corner is at <code>(settings.getWidth(),settings.getHeight())</code>.</div></li><li
class="level1"><div
class="li"> If you have several 2D elements in the <acronym
title="Graphical User Interface">GUI</acronym> bucket that overlap, define their depth order by specifing a Z value. You can use <code>pic.move(x, y, -2)</code> or <code>hudText.setLocalTranslation(x,y,-2)</code>.</div></li><li
class="level1"><div
class="li"> Size and length values in the orthogonal render queue are treated like pixels. A 20*20-wu big quad is rendered 20 pixels wide.</div></li></ul></div><h3><a
name="keeping_the_hud_up-to-date">Keeping the HUD Up-To-Date</a></h3><div
class="level3"><p> Use the update loop to keep the content up-to-date.</p><pre>public void simpleUpdate&#40;float tpf&#41; &#123;
guiNode.attachChild&#40;hudText&#41;;</pre>
<p>
The BitmapFont object <code>guiFont</code> is a default font provided by SimpleApplication. Copy you own fonts as .fnt plus .png files into the <code>assets/Interface/Fonts</code> directory and load them like this:
</p>
<pre>BitmapFont myFont = assetManager.loadFont(&quot;Interface/Fonts/Console.fnt&quot;);
hudText = new BitmapText(myFont, false);</pre>
</div>
<h3><a>Displaying Geometries in the HUD</a></h3>
<div>
<p>
It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static <acronym title="Graphical User Interface">GUI</acronym> elements. Note that if you use a lit Material, you must add a light to the guiNode. Also remember that size units are pixels in the HUD (a 2-wu cube is displayed tiny 2 pixels wide!).
</p>
</div>
<h3><a>Positioning HUD Elements</a></h3>
<div>
<ul>
<li><div> When positioning text and images in 2D, the bottom left corner of the screen is <code>(0f,0f)</code>, and the top right corner is at <code>(settings.getWidth(),settings.getHeight())</code>.</div>
</li>
<li><div> If you have several 2D elements in the <acronym title="Graphical User Interface">GUI</acronym> bucket that overlap, define their depth order by specifing a Z value. You can use <code>pic.move(x, y, -2)</code> or <code>hudText.setLocalTranslation(x,y,-2)</code>.</div>
</li>
<li><div> Size and length values in the orthogonal render queue are treated like pixels. A 20*20-wu big quad is rendered 20 pixels wide.</div>
</li>
</ul>
</div>
<h3><a>Keeping the HUD Up-To-Date</a></h3>
<div>
<p>
Use the update loop to keep the content up-to-date.
</p>
<pre>public void simpleUpdate&#40;float tpf&#41; &#123;
...
hudText.setText&#40;&quot;Score: &quot; + score&#41;;
...
picture.setImage&#40;assetManager, &quot;Interface/statechange.png&quot;, true&#41;;
...
&#125;</pre><div
class="tags"><span> <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>, <a
href="/wiki/doku.php/tag:display?do=showtag&amp;tag=tag%3Adisplay">display</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:hud?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
</div>
<h2><a>Advanced HUD: Nifty GUI</a></h2>
<div>
<p>
The recommended approach to create HUDs is using <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a>.
</p>
<ol>
<li><div> Lay out the <acronym title="Graphical User Interface">GUI</acronym> in one or several Nifty <acronym title="Extensible Markup Language">XML</acronym> or Java files. </div>
</li>
<li><div> Write the controller classes in Java.</div>
</li>
<li><div> Load the <acronym title="Extensible Markup Language">XML</acronym> file with the controller object in your game&#039;s simpleInit() method.</div>
</li>
</ol>
<p>
The advantage of Nifty <acronym title="Graphical User Interface">GUI</acronym> is that it is well integrated into jME and the jMonkeyPlatform, and that it offers all the features that you expect from a professional modern user interface.
</p>
<p>
For HUDs, you basically follow the same instructions as for creating a normal <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a>, you just don&#039;t pause the game while the HUD is up.
</p>
<div><span>
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>,
<a href="/wiki/doku.php/tag:display?do=showtag&amp;tag=tag%3Adisplay">display</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:hud?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

@ -1,135 +1,353 @@
<h1><a
name="input_handling">Input Handling</a></h1><div
class="level1"><p> Users interact with your jME3 application with different input devices – the mouse, the keyboard, or a joystick. To respond to inputs we use the <code>inputManager</code> object in <code>SimpleApplication</code>.</p><p> This is how you add interaction to your game:</p><ol><li
class="level1"><div
class="li"> For each action, choose the trigger(s) (a key or mouse click etc)</div></li><li
class="level1"><div
class="li"> For each action, add a trigger mapping to the inputManager</div></li><li
class="level1"><div
class="li"> Create at least one listener in SimpleApplication</div></li><li
class="level1"><div
class="li"> For each action, register its mappings to a listener</div></li><li
class="level1"><div
class="li"> Implement each action in the listener</div></li></ol></div><h2><a
name="choose_trigger">1. Choose Trigger</a></h2><div
class="level2"><p> Choose one or several key/mouse events for the interaction. We use <code>KeyTrigger</code>, <code>MouseAxisTrigger</code>, <code>MouseButtonTrigger</code>, <code>JoyAxisTrigger</code> and <code>JoyButtonTrigger</code> constants from the <code>com.jme3.input.controls</code> package.</p><p> The booleans are used to negate the axes: For inputs that have two axes (MouseAxis, JoyAxis), you have to listen to the negative (true) and positive (false) axis separately.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0"> Trigger</th><th
class="col1"> Code</th></tr><tr
class="row1"><td
class="col0"> Mouse button: Left Click</td><td
class="col1"> MouseButtonTrigger(MouseInput.BUTTON_LEFT)</td></tr><tr
class="row2"><td
class="col0"> Mouse button: Right Click</td><td
class="col1"> MouseButtonTrigger(MouseInput.BUTTON_RIGHT)</td></tr><tr
class="row3"><td
class="col0"> Mouse button: Middle Click</td><td
class="col1"> MouseButtonTrigger(MouseInput.BUTTON_MIDDLE)</td></tr><tr
class="row4"><td
class="col0"> Mouse movement:</td><td
class="col1"> MouseAxisTrigger(MouseInput.AXIS_X, true), <br/> MouseAxisTrigger(MouseInput.AXIS_Y, true), <br/> MouseAxisTrigger(MouseInput.AXIS_X, false), <br/> MouseAxisTrigger(MouseInput.AXIS_Y, false)</td></tr><tr
class="row5"><td
class="col0"> Mouse wheel:</td><td
class="col1"> MouseAxisTrigger(MouseInput.AXIS_WHEEL,false) <br/> MouseAxisTrigger(MouseInput.AXIS_WHEEL,true)</td></tr><tr
class="row6"><td
class="col0"> Keyboard: Characters and Numbers etc</td><td
class="col1"> KeyTrigger(KeyInput.KEY_X) etc</td></tr><tr
class="row7"><td
class="col0 leftalign"> Keyboard: Spacebar</td><td
class="col1"> KeyTrigger(KeyInput.KEY_SPACE)</td></tr><tr
class="row8"><td
class="col0"> Keyboard: Shift</td><td
class="col1"> KeyTrigger(KeyInput.KEY_RSHIFT), <br/> KeyTrigger(KeyInput.KEY_LSHIFT)</td></tr><tr
class="row9"><td
class="col0"> Keyboard: F1 etc</td><td
class="col1"> KeyTrigger(KeyInput.KEY_F1) etc</td></tr><tr
class="row10"><td
class="col0"> Keyboard: Return, Enter</td><td
class="col1 leftalign"> KeyTrigger(KeyInput.KEY_RETURN), <br/> KeyTrigger(KeyInput.KEY_NUMPADENTER)</td></tr><tr
class="row11"><td
class="col0"> Keyboard: PageUp, PageDown</td><td
class="col1"> KeyTrigger(KeyInput.KEY_PGUP), <br/> KeyTrigger(KeyInput.KEY_PGDN)</td></tr><tr
class="row12"><td
class="col0"> Keyboard: Delete, Backspace</td><td
class="col1"> KeyTrigger(KeyInput.KEY_BACK), <br/> KeyTrigger(KeyInput.KEY_DELETE)</td></tr><tr
class="row13"><td
class="col0"> Keyboard: Escape</td><td
class="col1"> KeyTrigger(KeyInput.KEY_ESCAPE)</td></tr><tr
class="row14"><td
class="col0"> Keyboard: Arrows</td><td
class="col1"> KeyTrigger(KeyInput.KEY_DOWN), <br/> KeyTrigger(KeyInput.KEY_UP) <br/> KeyTrigger(KeyInput.KEY_LEFT), KeyTrigger(KeyInput.KEY_RIGHT)</td></tr><tr
class="row15"><td
class="col0"> NumPad: Number 1 etc</td><td
class="col1"> KeyTrigger(KeyInput.KEY_NUMPAD1) etc</td></tr><tr
class="row16"><td
class="col0"> Joystick: Button</td><td
class="col1"> JoyButtonTrigger(0, JoyInput.AXIS_POV_X), <br/> JoyButtonTrigger(0, JoyInput.AXIS_POV_Y) ?</td></tr><tr
class="row17"><td
class="col0"> Joystick: Movement</td><td
class="col1"> JoyAxisTrigger(0, JoyInput.AXIS_POV_X, true), <br/> JoyAxisTrigger(0, JoyInput.AXIS_POV_X, false), <br/> JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, true), <br/> JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, false)</td></tr></table></div></div><h2><a
name="add_a_trigger_mapping">2. Add a Trigger Mapping</a></h2><div
class="level2"><p> When initializing the application, add a Mapping for each Trigger.</p><p> Give the mapping a meaningful name. The name should reflect the action, not the key, since the keys can change. Here some examples:</p><pre>inputManager.addMapping&#40;&quot;Pause Game&quot;, new KeyTrigger&#40;KeyInput.KEY_P&#41;&#41;;
inputManager.addMapping&#40;&quot;Rotate&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;</pre><p> There are cases where you may want more then one trigger for one action. For instance some users prefer the WASD keys to navigate, others prefer the arrow keys. You can define both by adding them after a comma.</p><pre>inputManager.addMapping&#40;&quot;Left&quot;, new KeyTrigger&#40;KeyInput.KEY_A&#41;,
new KeyTrigger&#40;KeyInput.KEY_LEFT&#41;&#41;;
<h1><a>Input Handling</a></h1>
<div>
<p>
Users interact with your jME3 application with different input devices – the mouse, the keyboard, or a joystick. To respond to inputs we use the <code>inputManager</code> object in <code>SimpleApplication</code>.
</p>
<p>
This is how you add interaction to your game:
</p>
<ol>
<li><div> For each action, choose the trigger(s) (a key or mouse click etc)</div>
</li>
<li><div> For each action, add a trigger mapping to the inputManager</div>
</li>
<li><div> Create at least one listener in SimpleApplication</div>
</li>
<li><div> For each action, register its mappings to a listener</div>
</li>
<li><div> Implement each action in the listener</div>
</li>
</ol>
</div>
<h2><a>1. Choose Trigger</a></h2>
<div>
<p>
Choose one or several key/mouse events for the interaction. We use <code>KeyTrigger</code>, <code>MouseAxisTrigger</code>, <code>MouseButtonTrigger</code>, <code>JoyAxisTrigger</code> and <code>JoyButtonTrigger</code> constants from the <code>com.jme3.input.controls</code> package.
</p>
<p>
<strong>Note:</strong> The MouseAxis and JoyAxis triggers go along the X axis (right/left) or Y axis (up/down). These Triggers come with extra booleans for the negative half of the axis (left, down). Remember to write code that listens to the negative (true) and positive (false) axis!
</p>
<div><table>
<tr>
<th> Trigger </th><th> Code </th>
</tr>
<tr>
<td> Mouse button: Left Click </td><td> MouseButtonTrigger(MouseInput.BUTTON_LEFT) </td>
</tr>
<tr>
<td> Mouse button: Right Click </td><td> MouseButtonTrigger(MouseInput.BUTTON_RIGHT) </td>
</tr>
<tr>
<td> Mouse button: Middle Click </td><td> MouseButtonTrigger(MouseInput.BUTTON_MIDDLE) </td>
</tr>
<tr>
<td> Mouse movement: Right </td><td> MouseAxisTrigger(MouseInput.AXIS_X, true) </td>
</tr>
<tr>
<td> Mouse movement: Left </td><td> MouseAxisTrigger(MouseInput.AXIS_X, false)</td>
</tr>
<tr>
<td> Mouse movement: Up </td><td> MouseAxisTrigger(MouseInput.AXIS_Y, true) </td>
</tr>
<tr>
<td> Mouse movement: Down </td><td> MouseAxisTrigger(MouseInput.AXIS_Y, false) </td>
</tr>
<tr>
<td> Mouse wheel: Up </td><td> MouseAxisTrigger(MouseInput.AXIS_WHEEL,false) </td>
</tr>
<tr>
<td> Mouse wheel: Down </td><td> MouseAxisTrigger(MouseInput.AXIS_WHEEL,true) </td>
</tr>
<tr>
<td> NumPad: 1, 2, 3, … </td><td> KeyTrigger(KeyInput.KEY_NUMPAD1) … </td>
</tr>
<tr>
<td> Keyboard: 1, 2 , 3, … </td><td> KeyTrigger(KeyInput.KEY_1) … </td>
</tr>
<tr>
<td> Keyboard: A, B, C, … </td><td> KeyTrigger(KeyInput.KEY_A) … </td>
</tr>
<tr>
<td> Keyboard: Spacebar </td><td> KeyTrigger(KeyInput.KEY_SPACE) </td>
</tr>
<tr>
<td> Keyboard: Shift </td><td> KeyTrigger(KeyInput.KEY_RSHIFT), <br/>
KeyTrigger(KeyInput.KEY_LSHIFT) </td>
</tr>
<tr>
<td> Keyboard: F1, F2, … </td><td> KeyTrigger(KeyInput.KEY_F1) … </td>
</tr>
<tr>
<td> Keyboard: Return, Enter </td><td> KeyTrigger(KeyInput.KEY_RETURN), <br/>
KeyTrigger(KeyInput.KEY_NUMPADENTER) </td>
</tr>
<tr>
<td> Keyboard: PageUp, PageDown </td><td> KeyTrigger(KeyInput.KEY_PGUP), <br/>
KeyTrigger(KeyInput.KEY_PGDN) </td>
</tr>
<tr>
<td> Keyboard: Delete, Backspace </td><td> KeyTrigger(KeyInput.KEY_BACK), <br/>
KeyTrigger(KeyInput.KEY_DELETE) </td>
</tr>
<tr>
<td> Keyboard: Escape </td><td> KeyTrigger(KeyInput.KEY_ESCAPE) </td>
</tr>
<tr>
<td> Keyboard: Arrows </td><td> KeyTrigger(KeyInput.KEY_DOWN), <br/>
KeyTrigger(KeyInput.KEY_UP) <br/>
KeyTrigger(KeyInput.KEY_LEFT), KeyTrigger(KeyInput.KEY_RIGHT) </td>
</tr>
<tr>
<td> Joystick Button: </td><td> JoyButtonTrigger(0, JoyInput.AXIS_POV_X), <br/>
JoyButtonTrigger(0, JoyInput.AXIS_POV_Y) ? </td>
</tr>
<tr>
<td> Joystick Movement: Right </td><td> JoyAxisTrigger(0, JoyInput.AXIS_POV_X, true) </td>
</tr>
<tr>
<td> Joystick Movement: Left </td><td> JoyAxisTrigger(0, JoyInput.AXIS_POV_X, false) </td>
</tr>
<tr>
<td> Joystick Movement: Forward </td><td> JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, true) </td>
</tr>
<tr>
<td> Joystick Movement: Backward</td><td> JoyAxisTrigger(0, JoyInput.AXIS_POV_Z, false) </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1098-3076] -->
<p>
In your IDE, use code completion to quickly look up Trigger literals. In the jMonkeyPlatform for example, press ctrl-space or ctrl-/ after <code>KeyInput.|</code> to choose from the list of all keys.
</p>
</div>
<h2><a>2. Add a Trigger Mapping</a></h2>
<div>
<p>
When initializing the application, add a Mapping for each Trigger.
</p>
<p>
Give the mapping a meaningful name. The name should reflect the action, not the button/key (because buttons/keys can change). Here some examples:
</p>
<pre>inputManager.addMapping&#40;&quot;Pause Game&quot;, new KeyTrigger&#40;KeyInput.KEY_P&#41;&#41;;
inputManager.addMapping&#40;&quot;Rotate&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;
...</pre>
<p>
There are cases where you may want to provide more then one trigger for one action. For example, some users prefer the WASD keys to navigate, while others prefer the arrow keys. Add several triggers for one mapping, by separating the Trigger objects with commas:
</p>
<pre>inputManager.addMapping&#40;&quot;Left&quot;, new KeyTrigger&#40;KeyInput.KEY_A&#41;,
new KeyTrigger&#40;KeyInput.KEY_LEFT&#41;&#41;; // A and left arrow
inputManager.addMapping&#40;&quot;Right&quot;, new KeyTrigger&#40;KeyInput.KEY_D&#41;,
new KeyTrigger&#40;KeyInput.KEY_RIGHT&#41;&#41;;</pre></div><h2><a
name="create_listeners">3. Create Listeners</a></h2><div
class="level2"><p> The jME3 input manager supports two types of event listeners for inputs:</p><p> <strong>com.jme3.input.controls.AnalogListener</strong></p><ul><li
class="level1"><div
class="li"> Use for continuous and gradual actions.</div><ul><li
class="level2"><div
class="li"> Examples: Walk, run, rotate, accelerate vehicle, strafe, (semi-)automatic weapon shot</div></li></ul></li><li
class="level1"><div
class="li"> JME gives you access to:</div><ul><li
class="level2"><div
class="li"> the name of the triggered action.</div></li><li
class="level2"><div
class="li"> a gradual value between 0-9 how long the key has been pressed.</div></li></ul></li></ul><p> <strong>com.jme3.input.controls.ActionListener</strong></p><ul><li
class="level1"><div
class="li"> Use for absolute &quot;pressed or released?&quot;, &quot;on or off?&quot; actions.</div><ul><li
class="level2"><div
class="li"> Examples: Pause/unpause, a rifle or revolver shot, jump, click to select.</div></li></ul></li><li
class="level1"><div
class="li"> JME gives you access to:</div><ul><li
class="level2"><div
class="li"> the name of the triggered action.</div></li><li
class="level2"><div
class="li"> a boolean whether the key is still pressed or has just been released.</div></li></ul></li></ul><p> You can use one or both in the same application. Add one or both of these code snippets to your main SimpleApplication-based class to activate the listener.</p><pre>private ActionListener&#40;&#41; &#123;
new KeyTrigger&#40;KeyInput.KEY_RIGHT&#41;&#41;; // D and right arrow
...</pre>
</div>
<h2><a>3. Create Listeners</a></h2>
<div>
<p>
The jME3 input manager supports two types of event listeners for inputs: AnalogListener and ActionListener. You can use one or both listeners in the same application. Add one or both of the following code snippets to your main SimpleApplication-based class to activate the listeners.
</p>
<p>
<strong>Note:</strong> The two input listeners do not know, and do not care, which actual key was pressed. They only know which <em>named input mapping</em> was triggered.
</p>
</div>
<h3><a>ActionListener</a></h3>
<div>
<p>
<code>com.jme3.input.controls.ActionListener</code>
</p>
<ul>
<li><div> Use for absolute &quot;button pressed or released?&quot;, &quot;on or off?&quot; actions. </div>
<ul>
<li><div> Examples: Pause/unpause, a rifle or revolver shot, jump, click to select.</div>
</li>
</ul>
</li>
<li><div> JME gives you access to:</div>
<ul>
<li><div> The mapping name of the triggered action.</div>
</li>
<li><div> A boolean whether the trigger is still pressed or has just been released.</div>
</li>
<li><div> A float of the current time-per-frame as timing factor</div>
</li>
</ul>
</li>
<li><div> </div>
</li>
</ul>
<pre>private ActionListener&#40;&#41; &#123;
public void onAction&#40;String name, boolean keyPressed, float tpf&#41; &#123;
/** TODO */
/** TODO: test for mapping names and implement actions */
&#125;
&#125;;</pre><pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
&#125;;</pre>
</div>
<h3><a>AnalogListener</a></h3>
<div>
<p>
<code>com.jme3.input.controls.AnalogListener</code>
</p>
<ul>
<li><div> Use for continuous and gradual actions.</div>
<ul>
<li><div> Examples: Walk, run, rotate, accelerate vehicle, strafe, (semi-)automatic weapon shot</div>
</li>
</ul>
</li>
<li><div> JME gives you access to:</div>
<ul>
<li><div> The mapping name of the triggered action.</div>
</li>
<li><div> A gradual float value between how long the trigger has been pressed.</div>
</li>
<li><div> A float of the current time-per-frame as timing factor</div>
</li>
</ul>
</li>
</ul>
<pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float keyPressed, float tpf&#41; &#123;
/** TODO */
/** TODO: test for mapping names and implement actions */
&#125;
&#125;;</pre></div><h2><a
name="register_mappings_to_listeners">4. Register Mappings to Listeners</a></h2><div
class="level2"><p> To activate the mappings, you must register them to the Listener. Write your registration code after the part where you have added the mappings to the inputManager before.</p><p> In this example, we register the &quot;Pause Game&quot; mapping to the <code>actionListener</code> object, because pausing a game is in &quot;either/or&quot; decision.</p><pre>inputManager.addListener&#40;actionListener, new String&#91;&#93;&#123;&quot;Left&quot;, &quot;Right&quot;&#125;&#41;;</pre><p> As you see, you can add several listeners in one String array. You can call the addListener() method more than once, each time with a subset of your list, if that helps you keep you code tidy.</p><p> <strong>Tip:</strong> Check the string&#039;s capitalization and spelling if you think you have registered an action, but it does not work.</p></div><h2><a
name="implement_actions">5. Implement Actions</a></h2><div
class="level2"><p> You specify the action to be triggered where it says TODO in the Listener code snippets.
Typically you write a series of if/else conditions, testing for all the mapping names, and specifying each action. Here is one example:</p><pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
&#125;;</pre>
</div>
<h2><a>4. Register Mappings to Listeners</a></h2>
<div>
<p>
To activate the mappings, you must register them to a Listener. Write your registration code after the code block where you have added the mappings to the inputManager.
</p>
<p>
In the following example, you register the &quot;Pause Game&quot; mapping to the <code>actionListener</code> object, because pausing a game is in &quot;either/or&quot; decision.
</p>
<pre>inputManager.addListener&#40;actionListener, new String&#91;&#93;&#123;&quot;Pause Game&quot;&#125;&#41;;</pre>
<p>
In the following example, you register navigational mappings to the <code>analogListener</code> object, because walking is a continuous action. Players typically keep the key pressed to express continuity, for example when they want to &quot;walk on&quot; or &quot;accelerate&quot;.
</p>
<pre>inputManager.addListener&#40;analogListener, new String&#91;&#93;&#123;&quot;Left&quot;, &quot;Right&quot;&#125;&#41;;</pre>
<p>
As you see, you can add several listeners in one String array. You can call the addListener() method more than once, each time with a subset of your list, if that helps you keep you code tidy. Again, the Listeners do not care about actual which keys are configured, you only register named trigger mappings.
</p>
<p>
<p><div>Did you register an action, but it does not work? Check the string&#039;s capitalization and spelling, it&#039;s case sensitive!
</div></p>
</p>
</div>
<h2><a>5. Implement Actions in Listeners</a></h2>
<div>
<p>
You specify the action to be triggered where it says TODO in the Listener code snippets. Typically, you write a series of if/else conditions, testing for all the mapping names, and then calling the respective action.
</p>
<p>
Make use of the distinction between <code>if</code> and <code>else if</code> in this conditional.
</p>
<ul>
<li><div> If several actions can be triggered simultaneously, test for all of these with a series of bare <code>if</code>s. For example, a character can be running forward <em>and</em> to the left.</div>
</li>
<li><div> If certain actions exclude one another, test for them with <code>else if</code>, the the rest of the exclusive tests can be skipped and you save some miliseconds. For example, you either shoot or pick something up.</div>
</li>
</ul>
</div>
<h3><a>ActionListener</a></h3>
<div>
<p>
In the most common case, you want an action to be triggered once, in the moment when the button or key trigger is released. For example, when the player presses a key to open a door, or clicks to pick up an item. For these cases, use an ActionListener and test for <code>&amp;&amp; !keyPressed</code>, like shown in the following example.
</p>
<pre>private ActionListener&#40;&#41; &#123;
public void onAction&#40;String name, boolean keyPressed, float tpf&#41; &#123;
&nbsp;
if &#40;name.equals&#40;&quot;Pause Game&quot;&#41; &amp;&amp; !keyPressed&#41; &#123; // test?
isRunning = !isRunning; // action!
&#125;
&nbsp;
if ...
&nbsp;
&#125;
&#125;;</pre>
</div>
<h3><a>AnalogListener</a></h3>
<div>
<p>
The following example shows how you define actions with an AnalogListener. Thiese actions are triggered continuously, as long (intensity <code>value</code>) as the named key or mouse button is down. Use this listeners for semi-automatic weapons and navigational actions.
</p>
<pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float value, float tpf&#41; &#123;
&nbsp;
if &#40;name.equals&#40;&quot;Rotate&quot;&#41;&#41; &#123; // test?
player.rotate&#40;0, value*speed, 0&#41;; // action!
&#125; // else if ...
&nbsp;
&#125;
&#125;;</pre><p> It&#039;s very common that you want an action to be only triggered once, in the moment when the key is released. Examples are when the player presses an action key to open a door or pick up an item, or to flip a game state, such as pause/unpause. For these cases, use an ActionListener and test for <code>&amp;&amp; !keyPressed</code>, like shown in the following example.</p><pre>private ActionListener&#40;&#41; &#123;
public void onAction&#40;String name, boolean keyPressed, float tpf&#41; &#123;
&nbsp;
if &#40;name.equals&#40;&quot;Pause Game&quot;&#41; &amp;&amp; !keyPressed&#41; &#123; // test?
isRunning = !isRunning; // action!
&#125; // else if ...
if ...
&nbsp;
&#125;
&#125;;</pre></div><h2><a
name="remapping_keys">Remapping Keys</a></h2><div
class="level2"><p> This approach of separating triggers from actions has the advantage that you can remap triggers easily. Maybe your players have different keyboard layouts, are used to &quot;reversed&quot; mouse navigation, or prefer different navigational keys than the ones you defined. In any case, you only need to replace the trigger parts in the <code>inputManager.addMapping()</code> lines with variables, and load different sets of trigger objects when the game starts. The rest of the code stays as it is.</p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>, <a
href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:input_handling?do=export_xhtmlbody">view online version</a></em></p>
&#125;;</pre>
</div>
<h2><a>Let Users Remap Keys</a></h2>
<div>
<p>
It is likely that your players have different keyboard layouts, are used to &quot;reversed&quot; mouse navigation, or prefer different navigational keys than the ones that you defined. You should create an options screen that lets users customize their mouse/key triggers for your mappings. Replace the trigger literals in the <code>inputManager.addMapping()</code> lines with variables, and load sets of triggers when the game starts.
</p>
<p>
The abstraction of separating triggers and mappings has the advantage that you can remap triggers easily. Your code only needs to remove and add some trigger mappings. The core of the code (the listeners and actions) remains unchanged.
</p>
<div><span>
<a href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:input_handling?do=export_xhtmlbody">view online version</a></em></p>

@ -1,16 +1,22 @@
<h1><a
name="saving_and_loading_materials_with_j3m_files">Saving and Loading Materials with .j3m Files</a></h1><div
class="level1"><p> In the <a
href="/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html">Material Definitions</a> article you learned how to configure <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials</a> programmatically in Java code. If you have certain commonly used Materials that never change, you can clean up the amount of Java code that clutters your init method, by moving material settings into .j3m files. Then later in your code, you only need to call one setter instead of several to apply the material.</p></div><h2><a
name="writing_the_j3m_file">Writing the .j3m File</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> For every Material, create a file and give it a name that describes it: e.g. <code>SimpleBump.j3m</code></div></li><li
class="level1"><div
class="li"> Place the file in your project&#039;s <code>assets/Materials/</code> directory, e.g. <code>MyGame/src/assets/Materials/SimpleBump.j3m</code></div></li><li
class="level1"><div
class="li"> Edit the file and add content using the following Syntax, e.g.:<pre>Material shiny bumpy rock : Common/MatDefs/Light/Lighting.j3md {
<h1><a>Saving and Loading Materials with .j3m Files</a></h1>
<div>
<p>
In the <a href="/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html">Material Definitions</a> article you learned how to configure <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials</a> programmatically in Java code. If you have certain commonly used Materials that never change, you can clean up the amount of Java code that clutters your init method, by moving material settings into .j3m files. Then later in your code, you only need to call one setter instead of several to apply the material.
</p>
</div>
<h2><a>Writing the .j3m File</a></h2>
<div>
<ol>
<li><div> For every Material, create a file and give it a name that describes it: e.g. <code>SimpleBump.j3m</code></div>
</li>
<li><div> Place the file in your project&#039;s <code>assets/Materials/</code> directory, e.g. <code>MyGame/src/assets/Materials/SimpleBump.j3m</code></div>
</li>
<li><div> Edit the file and add content using the following Syntax, e.g.:<pre>Material shiny bumpy rock : Common/MatDefs/Light/Lighting.j3md {
MaterialParameters {
Shininess: 8.0
NormalMap: Textures/bump_rock_normal.png
@ -19,190 +25,241 @@ class="li"> Edit the file and add content using the following Syntax, e.g.:<pre>
Diffuse : 1.0 1.0 1.0 1.0
Specular : 0.0 0.0 0.0 1.0
}
}</pre></div></li></ol><p> How to this file is structured:</p><ol><li
class="level1"><div
class="li"> Header</div><ol><li
class="level2"><div
class="li"> <code>Material</code> is a fixed keyword, keep it.</div></li><li
class="level2"><div
class="li"> <code>shiny bumpy rock</code> is a descriptive string that you can make up. Choose a name to help you remember for what you intend to use this material.</div></li><li
class="level2"><div
class="li"> After the colon, specify on which <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> definition you base this Material.</div></li></ol></li><li
class="level1"><div
class="li"> Now look up the choosen Material Definition&#039;s parameters and their parameter types from the <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> table. Add one line for each parameter.</div><ul><li
class="level2"><div
class="li"> For example: The series of four numbers in the example above represent RGBA color values.</div></li></ul></li><li
class="level1"><div
class="li"> Check the detailed syntax reference below if you are unsure.</div></li></ol><p> <strong>Tip:</strong> In the jMonkeyPlatform, use File&gt;New File&gt;Material&gt;Empty Material File to create .j3m files.</p></div><h2><a
name="how_to_use_j3m_materials">How to Use .j3m Materials</a></h2><div
class="level2"><p> This is how you use the prepared .j3m Material on a Spatial. Since you have saved the .j3m file to your project&#039;s Assets directory, the .j3m path is relative to <code>MyGame/src/assets/…</code>.</p><pre>myGeometry.setMaterial&#40;assetManager.loadAsset&#40;&quot;Materials/SimpleBump.j3m&quot;&#41;&#41;;</pre><p> <strong>Tip:</strong> In the jMonkeyPlatform, open Windows&gt;Palette and drag the <code>JME Material: Set J3M</code> snippet into your code.</p></div><h2><a
name="syntax_reference_for_j3m_files">Syntax Reference for .j3m Files</a></h2><div
class="level2"></div><h3><a
name="paths">Paths</a></h3><div
class="level3"><p> Make sure to get the paths to the textures (.png, .jpg) and material definitions (.j3md) right.</p><ul><li
class="level1"><div
class="li"> The paths to the built-in .j3md files are relative to jME3&#039;s Core Data directory. Just copy the path stated in the <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> table. <br/> <code>Common/MatDefs/Misc/Unshaded.j3md</code> is resolved to <code>jme3/src/src/core-data/Common/MatDefs/Misc/Unshaded.j3md</code>.</div></li><li
class="level1"><div
class="li"> The paths to your textures are relative to your project&#039;s assets directory. <br/> <code>Textures/bump_rock_normal.png</code> is resolved to <code>MyGame/src/assets/Textures/bump_rock_normal.png</code></div></li></ul></div><h3><a
name="data_types">Data Types</a></h3><div
class="level3"><p> All data types (except Color) are specified in com.jme3.shader.VarType.
&quot;Color&quot; is specified as Vector4 in J3MLoader.java.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">Name</th><th
class="col1">jME Java class</th><th
class="col2">.j3m file syntax</th></tr><tr
class="row1"><td
class="col0"> Float</td><td
class="col1"></td><td
class="col2"> a float (e.g. 0.72) , no comma or parentheses</td></tr><tr
class="row2"><td
class="col0"> Vector2</td><td
class="col1"> <code>com.jme3.math.Vector2f</code></td><td
class="col2"> Two floats, no comma or parentheses</td></tr><tr
class="row3"><td
class="col0"> Vector3</td><td
class="col1"> <code>com.jme3.math.Vector3f</code></td><td
class="col2"> Three floats, no comma or parentheses</td></tr><tr
class="row4"><td
class="col0"> Texture2D</td><td
class="col1"> <code>com.jme3.texture.Texture</code></td><td
class="col2"> Path to texture in <code>assets</code> directory, no quotation marks</td></tr><tr
class="row5"><td
class="col0"> Boolean</td><td
class="col1"> (basic Java type)</td><td
class="col2"> <code>true</code> or <code>false</code></td></tr><tr
class="row6"><td
class="col0"> Int</td><td
class="col1"> (basic Java type)</td><td
class="col2"> Integer number, no comma or parentheses</td></tr><tr
class="row7"><td
class="col0"> Color</td><td
class="col1"> <code>com.jme3.math.ColorRGBA</code></td><td
class="col2"> Four floats, no comma or parentheses</td></tr><tr
class="row8"><td
class="col0"> Vector4</td><td
class="col1 leftalign"></td><td
class="col2 leftalign"></td></tr><tr
class="row9"><td
class="col0"> FloatArray</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row10"><td
class="col0"> Vector2Array</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row11"><td
class="col0"> Vector3Array</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row12"><td
class="col0"> Vector4Array</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row13"><td
class="col0"> Matrix3</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row14"><td
class="col0"> Matrix4</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row15"><td
class="col0"> Matrix3Array</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row16"><td
class="col0"> Matrix4Array</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row17"><td
class="col0"> TextureBuffer</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row18"><td
class="col0"> Texture3D</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row19"><td
class="col0"> TextureArray</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr><tr
class="row20"><td
class="col0"> TextureCubeMap</td><td
class="col1"></td><td
class="col2 leftalign"></td></tr></table></div></div><h3><a
name="flip_and_repeat_syntax">Flip and Repeat Syntax</a></h3><div
class="level3"><ul><li
class="level1"><div
class="li"> A texture can be flipped using the following syntax <code>NormalMap: Flip Textures/bump_rock_normal.png</code></div></li><li
class="level1"><div
class="li"> A texture can be set to repeat using the following syntax <code>NormalMap: Repeat Textures/bump_rock_normal.png</code></div></li><li
class="level1"><div
class="li"> If a texture is set to both being flipped and repeated, Flip must come before Repeat</div></li></ul></div><h3><a
name="syntax_for_additional_render_states">Syntax for Additional Render States</a></h3><div
class="level3"><ul><li
class="level1"><div
class="li"> A Boolean can be &quot;On&quot; or &quot;Off&quot;</div></li><li
class="level1"><div
class="li"> Float is &quot;123.0&quot; etc</div></li><li
class="level1"><div
class="li"> Enum - values depend on the enum</div></li></ul><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">Name</th><th
class="col1">Type</th><th
class="col2">Purpose</th></tr><tr
class="row1"><td
class="col0">Wireframe</td><td
class="col1">(Boolean)</td><td
class="col2"></td></tr><tr
class="row2"><td
class="col0">FaceCull</td><td
class="col1">(Enum: FaceCullMode)</td><td
class="col2"></td></tr><tr
class="row3"><td
class="col0">DepthWrite</td><td
class="col1">(Boolean)</td><td
class="col2"></td></tr><tr
class="row4"><td
class="col0">DepthTest</td><td
class="col1">(Boolean)</td><td
class="col2"></td></tr><tr
class="row5"><td
class="col0">Blend</td><td
class="col1">(Enum: BlendMode)</td><td
class="col2"></td></tr><tr
class="row6"><td
class="col0">AlphaTestFalloff</td><td
class="col1">(Float)</td><td
class="col2"></td></tr><tr
class="row7"><td
class="col0">PolyOffset</td><td
class="col1">(Float, Float)</td><td
class="col2"></td></tr><tr
class="row8"><td
class="col0">ColorWrite</td><td
class="col1">(Boolean)</td><td
class="col2"></td></tr><tr
class="row9"><td
class="col0">PointSprite</td><td
class="col1">(Boolean)</td><td
class="col2"></td></tr></table></div></div><h2><a
name="examples">Examples</a></h2><div
class="level2"></div><h3><a
name="example_1shiny">Example 1: Shiny</a></h3><div
class="level3"><pre>Spatial signpost = &#40;Spatial&#41; assetManager.loadAsset&#40;
}</pre>
</div>
</li>
</ol>
<p>
How to this file is structured:
</p>
<ol>
<li><div> Header</div>
<ol>
<li><div> <code>Material</code> is a fixed keyword, keep it.</div>
</li>
<li><div> <code>shiny bumpy rock</code> is a descriptive string that you can make up. Choose a name to help you remember for what you intend to use this material.</div>
</li>
<li><div> After the colon, specify on which <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> definition you base this Material.</div>
</li>
</ol>
</li>
<li><div> Now look up the choosen Material Definition&#039;s parameters and their parameter types from the <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> table. Add one line for each parameter.</div>
<ul>
<li><div> For example: The series of four numbers in the example above represent RGBA color values.</div>
</li>
</ul>
</li>
<li><div> Check the detailed syntax reference below if you are unsure.</div>
</li>
</ol>
<p>
<strong>Tip:</strong> In the jMonkeyPlatform, use File&gt;New File&gt;Material&gt;Empty Material File to create .j3m files.
</p>
</div>
<h2><a>How to Use .j3m Materials</a></h2>
<div>
<p>
This is how you use the prepared .j3m Material on a Spatial. Since you have saved the .j3m file to your project&#039;s Assets directory, the .j3m path is relative to <code>MyGame/src/assets/…</code>.
</p>
<pre>myGeometry.setMaterial&#40;assetManager.loadAsset&#40;&quot;Materials/SimpleBump.j3m&quot;&#41;&#41;;</pre>
<p>
<strong>Tip:</strong> In the jMonkeyPlatform, open Windows&gt;Palette and drag the <code>JME Material: Set J3M</code> snippet into your code.
</p>
</div>
<h2><a>Syntax Reference for .j3m Files</a></h2>
<div>
</div>
<h3><a>Paths</a></h3>
<div>
<p>
Make sure to get the paths to the textures (.png, .jpg) and material definitions (.j3md) right.
</p>
<ul>
<li><div> The paths to the built-in .j3md files are relative to jME3&#039;s Core Data directory. Just copy the path stated in the <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Material</a> table. <br/>
<code>Common/MatDefs/Misc/Unshaded.j3md</code> is resolved to <code>jme3/src/src/core-data/Common/MatDefs/Misc/Unshaded.j3md</code>.</div>
</li>
<li><div> The paths to your textures are relative to your project&#039;s assets directory. <br/>
<code>Textures/bump_rock_normal.png</code> is resolved to <code>MyGame/src/assets/Textures/bump_rock_normal.png</code></div>
</li>
</ul>
</div>
<h3><a>Data Types</a></h3>
<div>
<p>
All data types (except Color) are specified in com.jme3.shader.VarType.
&quot;Color&quot; is specified as Vector4 in J3MLoader.java.
</p>
<div><table>
<tr>
<th>Name</th><th>jME Java class</th><th>.j3m file syntax</th>
</tr>
<tr>
<td> Float</td><td> (basic Java type) </td><td> a float (e.g. 0.72) , no comma or parentheses </td>
</tr>
<tr>
<td> Vector2</td><td> <code>com.jme3.math.Vector2f</code></td><td> Two floats, no comma or parentheses </td>
</tr>
<tr>
<td> Vector3 </td><td> <code>com.jme3.math.Vector3f</code> </td><td> Three floats, no comma or parentheses </td>
</tr>
<tr>
<td> Vector4</td><td> <code>com.jme3.math.Vector4f</code> </td><td> Four floats, no comma or parentheses </td>
</tr>
<tr>
<td> Texture2D </td><td> <code>com.jme3.texture.Texture2D</code> </td><td> Path to texture in <code>assets</code> directory, no quotation marks </td>
</tr>
<tr>
<td> Texture3D</td><td> <code>com.jme3.texture.Texture3D</code> </td><td> Same as texture 2D except it is interpreted as a 3D texture </td>
</tr>
<tr>
<td> TextureCubeMap</td><td> <code>com.jme3.texture.TextureCubeMap</code> </td><td> Same as texture 2D except it is interpreted as a cubemap texture </td>
</tr>
<tr>
<td> Boolean</td><td> (basic Java type) </td><td> <code>true</code> or <code>false</code> </td>
</tr>
<tr>
<td> Int</td><td> (basic Java type) </td><td> Integer number, no comma or parentheses </td>
</tr>
<tr>
<td> Color </td><td> <code>com.jme3.math.ColorRGBA</code> </td><td> Four floats, no comma or parentheses </td>
</tr>
<tr>
<td> FloatArray</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Vector2Array</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Vector3Array</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Vector4Array</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Matrix3</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Matrix4</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Matrix3Array</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> Matrix4Array</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> TextureBuffer</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
<tr>
<td> TextureArray</td><td> </td><td> (Currently not supported in J3M) </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3125-4539] -->
</div>
<h3><a>Flip and Repeat Syntax</a></h3>
<div>
<ul>
<li><div> A texture can be flipped using the following syntax <code>NormalMap: Flip Textures/bump_rock_normal.png</code></div>
</li>
<li><div> A texture can be set to repeat using the following syntax <code>NormalMap: Repeat Textures/bump_rock_normal.png</code></div>
</li>
<li><div> If a texture is set to both being flipped and repeated, Flip must come before Repeat</div>
</li>
</ul>
</div>
<h3><a>Syntax for Additional Render States</a></h3>
<div>
<ul>
<li><div> A Boolean can be &quot;On&quot; or &quot;Off&quot;</div>
</li>
<li><div> Float is &quot;123.0&quot; etc</div>
</li>
<li><div> Enum - values depend on the enum</div>
</li>
</ul>
<p>
See the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html"><param name="text" value="<html><u>RenderState</u></html>"><param name="textColor" value="blue"></object> javadoc for a detailed explanation of render states.
</p>
<div><table>
<tr>
<th>Name</th><th>Type</th><th>Purpose</th>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setWireframe(boolean)"><param name="text" value="<html><u>Wireframe</u></html>"><param name="textColor" value="blue"></object> </td><td>(Boolean)</td><td> Enable wireframe rendering mode </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)"><param name="text" value="<html><u>FaceCull</u></html>"><param name="textColor" value="blue"></object> </td><td>(Enum: FaceCullMode)</td><td> Set face culling mode (Off, Front, Back, FrontAndBack) </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setDepthWrite(boolean)"><param name="text" value="<html><u>DepthWrite</u></html>"><param name="textColor" value="blue"></object> </td><td>(Boolean)</td><td> Enable writing depth to the depth buffer </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setDepthTest(boolean)"><param name="text" value="<html><u>DepthTest</u></html>"><param name="textColor" value="blue"></object> </td><td>(Boolean)</td><td> Enable depth testing </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setBlendMode(com.jme3.material.RenderState.BlendMode)"><param name="text" value="<html><u>Blend</u></html>"><param name="textColor" value="blue"></object> </td><td>(Enum: BlendMode)</td><td> Set the blending mode </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setAlphaFallOff(float)"><param name="text" value="<html><u>AlphaTestFalloff</u></html>"><param name="textColor" value="blue"></object> </td><td>(Float)</td><td> Set the alpha testing alpha falloff value (if set, it will enable alpha testing) </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setPolyOffset(float, float)"><param name="text" value="<html><u>PolyOffset</u></html>"><param name="textColor" value="blue"></object> </td><td>(Float, Float)</td><td> Set the polygon offset factor and units </td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setColorWrite(boolean)"><param name="text" value="<html><u>ColorWrite</u></html>"><param name="textColor" value="blue"></object> </td><td>(Boolean)</td><td> Enable color writing</td>
</tr>
<tr>
<td> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/javadoc/com/jme3/material/RenderState.html#setPointSprite(boolean)"><param name="text" value="<html><u>PointSprite</u></html>"><param name="textColor" value="blue"></object> </td><td>(Boolean)</td><td> Enable point sprite rendering for point meshes </td>
</tr>
</table></div>
<!-- EDIT2 TABLE [5177-6745] -->
</div>
<h2><a>Examples</a></h2>
<div>
</div>
<h3><a>Example 1: Shiny</a></h3>
<div>
<pre>Spatial signpost = &#40;Spatial&#41; assetManager.loadAsset&#40;
new OgreMeshKey&#40;&quot;Models/Sign Post/Sign Post.mesh.xml&quot;, null&#41;&#41;;
signpost.setMaterial&#40; &#40;Material&#41; assetManager.loadAsset&#40;
new AssetKey&#40;&quot;Models/Sign Post/Sign Post.j3m&quot;&#41;&#41;&#41;;
TangentBinormalGenerator.generate&#40;signpost&#41;;
rootNode.attachChild&#40;signpost&#41;;</pre><p> The file <code>assets/Models/Sign Post/Sign Post.j3m</code> contains:</p><pre>Material Signpost : Common/MatDefs/Light/Lighting.j3md {
rootNode.attachChild&#40;signpost&#41;;</pre>
<p>
The file <code>assets/Models/Sign Post/Sign Post.j3m</code> contains:
</p>
<pre>Material Signpost : Common/MatDefs/Light/Lighting.j3md {
MaterialParameters {
Shininess: 4.0
DiffuseMap: Models/Sign Post/Sign Post.jpg
@ -213,24 +270,50 @@ rootNode.attachChild&#40;signpost&#41;;</pre><p> The file <code>assets/Models/Si
Diffuse : 1.0 1.0 1.0 1.0
Specular : 1.0 1.0 1.0 1.0
}
}</pre><p> The <acronym
title="Joint Photographics Experts Group">JPG</acronym> files are in the same directory, <code>assets/Models/Sign Post/…</code>.</p></div><h3><a
name="example_2repeating_texture">Example 2: Repeating Texture</a></h3><div
class="level3"><pre>Material mat = assetManager.loadMaterial&#40;
}</pre>
<p>
The <acronym title="Joint Photographics Experts Group">JPG</acronym> files are in the same directory, <code>assets/Models/Sign Post/…</code>.
</p>
</div>
<h3><a>Example 2: Repeating Texture</a></h3>
<div>
<pre>Material mat = assetManager.loadMaterial&#40;
&quot;Textures/Terrain/Pond/Pond.j3m&quot;&#41;;
mat.setColor&#40;&quot;Ambient&quot;, ColorRGBA.DarkGray&#41;;
mat.setColor&#40;&quot;Diffuse&quot;, ColorRGBA.White&#41;;
mat.setBoolean&#40;&quot;UseMaterialColors&quot;, true&#41;;</pre><p> The file <code>assets/Textures/Terrain/Pond/Pond.j3m</code> contains:</p><pre>Material Pong Rock : Common/MatDefs/Light/Lighting.j3md {
mat.setBoolean&#40;&quot;UseMaterialColors&quot;, true&#41;;</pre>
<p>
The file <code>assets/Textures/Terrain/Pond/Pond.j3m</code> contains:
</p>
<pre>Material Pong Rock : Common/MatDefs/Light/Lighting.j3md {
MaterialParameters {
Shininess: 8.0
DiffuseMap: Repeat Textures/Terrain/Pond/Pond.png
NormalMap: Repeat Textures/Terrain/Pond/Pond_normal.png
}
}</pre><p> The <acronym
title="Portable Network Graphics">PNG</acronym> files are in the same directory, <code>assets/Textures/Terrain/Pond/</code></p></div><h3><a
name="example_3transparent">Example 3: Transparent</a></h3><div
class="level3"><p> The file <code>assets/Models/Tree/Leaves.j3m</code> contains:</p><pre>Material Leaves : Common/MatDefs/Light/Lighting.j3md {
}</pre>
<p>
The <acronym title="Portable Network Graphics">PNG</acronym> files are in the same directory, <code>assets/Textures/Terrain/Pond/</code>
</p>
</div>
<h3><a>Example 3: Transparent</a></h3>
<div>
<p>
The file <code>assets/Models/Tree/Leaves.j3m</code> contains:
</p>
<pre>Material Leaves : Common/MatDefs/Light/Lighting.j3md {
Transparent On
MaterialParameters {
DiffuseMap : Models/Tree/Leaves.png
UseAlpha : true
@ -246,6 +329,11 @@ class="level3"><p> The file <code>assets/Models/Tree/Leaves.j3m</code> contains:
AlphaTestFalloff 0.50
FaceCull Off
}
}</pre><p> The <acronym
title="Portable Network Graphics">PNG</acronym> file is in the same directory, <code>assets/Models/Tree/…</code></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:j3m_material_files?do=export_xhtmlbody">view online version</a></em></p>
}</pre>
<p>
The <acronym title="Portable Network Graphics">PNG</acronym> file is in the same directory, <code>assets/Models/Tree/…</code>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:j3m_material_files?do=export_xhtmlbody">view online version</a></em></p>

@ -1,32 +1,109 @@
<h1><a
name="jme3_and_shaders">JME3 and Shaders</a></h1><div
class="level1"><p> <br/></p></div><h1><a
name="shaders_basics">Shaders Basics</a></h1><div
class="level1"><p> Shaders are sets of instructions that are executed on the GPU. They are used to take advantage of hardware acceleration available on the GPU for rendering purposes.<br/> This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,…).<br/> There are multiple frequently used languages that you may encounter to code shaders but as JME3 is based on OpenGL, shaders in JME use GLSL and any example in this paper will be written in GLSL.<br/> <br/></p></div><h3><a
name="how_does_it_work">How Does it work?</a></h3><div
class="level3"><p> To keep it Simple: The Vertex shader is executed once for each vertex in the view, then the Fragment shader (also called the Pixel shader) is executed once for each pixel on the screen.<br/> The main purpose of the Vertex shader is to compute the screen coordinate of a vertex (where this vertex will be displayed on screen) while the main purpose of the Fragment shader is to compute the color of a pixel.<br/> This is a very simplified graphic to describe the call stack: <br/> <a
href="/wiki/lib/exe/fetch.php?hash=d919e8&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F09%2FJME3andShaders.png"><img
src="/wiki/lib/exe/fetch.php?hash=d919e8&amp;w=250&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F09%2FJME3andShaders.png" class="media" alt="" width="250" /></a><br/> The main program sends mesh data to the vertex shader (vertex position in object space, normals, tangents, etc..). The vertex shader computes the screen position of the vertex and sends it to the Fragment shader. The fragment shader computes the color, and the result is displayed on screen or in a texture. <br/></p></div><h3><a
name="variables_scope">Variables scope</a></h3><div
class="level3"><p> There are different types of scope for variables in a shader :</p><ul><li
class="level1"><div
class="li"> uniform : User defined variables that are passed by the main program to the vertex and fragment shader, these variables are global for a given execution of a shader.</div></li><li
class="level1"><div
class="li"> attribute : Per-vertex variables passed by the engine to the shader, like position, normal, etc (Mesh data in the graphic)</div></li><li
class="level1"><div
class="li"> varrying : Variables passed from the vertex shader to the fragment shader.</div></li></ul><p> There is a large panel of variable types to be used, for more information about it I recommend reading the GLSL specification <a
href="http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf">here</a>.<br/> <br/></p></div><h3><a
name="spaces_and_matrices">Spaces and Matrices</a></h3><div
class="level3"><p> To understand the coming example you must know about the different spaces in 3D computer graphics, and the matrices used to translate coordinate from one space to another.<br/> <a
href="/wiki/lib/exe/fetch.php?hash=65c1f0&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F09%2FJME3andShaders-1.png"><img
src="/wiki/lib/exe/fetch.php?hash=65c1f0&amp;media=http%3A%2F%2Fjmonkeyengine.org%2Fwp-content%2Fuploads%2F2010%2F09%2FJME3andShaders-1.png" class="media" alt="" /></a><br/> The engine passes the object space coordinates to the vertex shader. We need to compute its position in projection space. To do that we transform the object space position by the WorldViewProjectionMatrix which is a combination of the World, View, Projection matrices (who would have guessed?).<br/> <br/></p></div><h3><a
name="simple_example_rendering_a_solid_color_on_an_object">Simple example : rendering a solid color on an object</a></h3><div
class="level3"><p> Here is the simplest application to shaders, rendering a solid color.<br/> Vertex Shader : <br/></p><pre>//the global uniform World view projection matrix
<h1><a>JME3 and Shaders</a></h1>
<div>
<p>
<br/>
</p>
</div>
<h1><a>Shaders Basics</a></h1>
<div>
<p>
Shaders are sets of instructions that are executed on the GPU. They are used to take advantage of hardware acceleration available on the GPU for rendering purposes.<br/>
This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,…).<br/>
There are multiple frequently used languages that you may encounter to code shaders but as JME3 is based on OpenGL, shaders in JME use GLSL and any example in this paper will be written in GLSL.<br/>
<br/>
</p>
</div>
<h3><a>How Does it work?</a></h3>
<div>
<p>
To keep it Simple: The Vertex shader is executed once for each vertex in the view, then the Fragment shader (also called the Pixel shader) is executed once for each pixel on the screen.<br/>
The main purpose of the Vertex shader is to compute the screen coordinate of a vertex (where this vertex will be displayed on screen) while the main purpose of the Fragment shader is to compute the color of a pixel.<br/>
This is a very simplified graphic to describe the call stack: <br/>
<img src="/wiki/lib/exe/fetch.php"><br/>
The main program sends mesh data to the vertex shader (vertex position in object space, normals, tangents, etc..). The vertex shader computes the screen position of the vertex and sends it to the Fragment shader. The fragment shader computes the color, and the result is displayed on screen or in a texture.
<br/>
</p>
</div>
<h3><a>Variables scope</a></h3>
<div>
<p>
There are different types of scope for variables in a shader :
</p>
<ul>
<li><div> uniform : User defined variables that are passed by the main program to the vertex and fragment shader, these variables are global for a given execution of a shader.</div>
</li>
<li><div> attribute : Per-vertex variables passed by the engine to the shader, like position, normal, etc (Mesh data in the graphic)</div>
</li>
<li><div> varrying : Variables passed from the vertex shader to the fragment shader.</div>
</li>
</ul>
<p>
There is a large panel of variable types to be used, for more information about it I recommend reading the GLSL specification <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf"><param name="text" value="<html><u>here</u></html>"><param name="textColor" value="blue"></object>.<br/>
<br/>
</p>
</div>
<h3><a>Spaces and Matrices</a></h3>
<div>
<p>
To understand the coming example you must know about the different spaces in 3D computer graphics, and the matrices used to translate coordinate from one space to another.<br/>
<img src="/wiki/lib/exe/fetch.php"><br/>
The engine passes the object space coordinates to the vertex shader. We need to compute its position in projection space. To do that we transform the object space position by the WorldViewProjectionMatrix which is a combination of the World, View, Projection matrices (who would have guessed?).<br/>
<br/>
</p>
</div>
<h3><a>Simple example : rendering a solid color on an object</a></h3>
<div>
<p>
Here is the simplest application to shaders, rendering a solid color.<br/>
Vertex Shader : <br/>
</p>
<pre>//the global uniform World view projection matrix
//(more on global uniforms below)
uniform mat4 g_WorldViewProjectionMatrix;
//The attribute inPosition is the Object space position of the vertex
attribute vec3 inPosition;
&nbsp;
void main&#40;&#41;&#123;
//Transformation of the object space coordinate to projection space
//coordinates.
@ -36,26 +113,57 @@ void main&#40;&#41;&#123;
//by the position vector.
//The multiplication must be done in this order.
gl_Position = g_WorldViewProjectionMatrix * vec4&#40;inPosition, 1.0&#41;;
&#125;</pre><p> Fragment Shader : <br/></p><pre>void main&#40;&#41;&#123;
&#125;</pre>
<p>
Fragment Shader : <br/>
</p>
<pre>void main&#40;&#41;&#123;
//returning the color of the pixel (here solid blue)
//- gl_FragColor is the standard GLSL variable that holds the pixel
//color. It must be filled in the Fragment Shader.
gl_FragColor = vec4&#40;0.0, 0.0, 1.0, 1.0&#41;;
&#125;</pre><p> For example applying this shader to a sphere would render a solid blue sphere on screen.<br/> <br/></p></div><h1><a
name="how_to_use_shaders_in_jme3">How to use shaders in JME3</a></h1><div
class="level1"><p> You probably heard that JME3 is “shader oriented”, but what does that mean?<br/> Usually to use shaders you must create what is called a program. This program specify the vertex shader and the fragment shader to use.<br/> JME3 encloses this in the material system. Every material in JME3 uses shaders.<br/> For example let’s have a look at the SolidColor.j3md file : <br/></p><pre>MaterialDef Solid Color &#123;
&#125;</pre>
<p>
For example applying this shader to a sphere would render a solid blue sphere on screen.<br/>
<br/>
</p>
</div>
<h1><a>How to use shaders in JME3</a></h1>
<div>
<p>
You probably heard that JME3 is “shader oriented”, but what does that mean?<br/>
Usually to use shaders you must create what is called a program. This program specify the vertex shader and the fragment shader to use.<br/>
JME3 encloses this in the material system. Every material in JME3 uses shaders.<br/>
For example let’s have a look at the SolidColor.j3md file : <br/>
</p>
<pre>MaterialDef Solid Color &#123;
//This is the complete list of user defined uniforms to be used in the
//shaders
MaterialParameters &#123;
Vector4 Color
&#125;
&nbsp;
Technique &#123;
//This is where the vertex and fragment shader files are
//specified
VertexShader GLSL100: Common/MatDefs/Misc/SolidColor.vert
FragmentShader GLSL100: Common/MatDefs/Misc/SolidColor.frag
&nbsp;
//This is where you specify which global uniform you need for your
//shaders
WorldParameters &#123;
@ -64,67 +172,171 @@ class="level1"><p> You probably heard that JME3 is “shader oriented”, but wh
&#125;
Technique FixedFunc &#123;
&#125;
&#125;</pre><p> For more information on JME3 material system, i suggest you read this <a
href="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/jmonkeyengine3-material-system-full-explanation">topic</a>.<br/> <br/></p></div><h3><a
name="jme3_global_uniforms">JME3 Global uniforms</a></h3><div
class="level3"><p> JME3 can expose pre-computed global uniforms to your shaders. You must specify the one that are required for your shader in the WorldParameters section of the material definition file (.j3md).<br/> Note that in the shader the uniform names will be prefixed by a “g_”.<br/> In the example above, WorldViewProjectionMatrix is declared as uniform mat4 g_WorldViewProjectionMatrix in the shader.<br/> The complete list of global uniforms that can be used in JME3 can be found <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/shader/UniformBinding.java">here</a>.<br/> <br/></p></div><h3><a
name="jme3_attributes">JME3 attributes</a></h3><div
class="level3"><p> Those are different attributes that are always passed to your shader.<br/> you can find a complete list of those attribute in the Type enum of the VertexBuffer <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/VertexBuffer.java">here</a>.<br/> Note that in the shader the attributes names will be prefixed by a “in”.<br/> <br/></p></div><h3><a
name="user_s_uniforms">User&#039;s uniforms</a></h3><div
class="level3"><p> At some point when making your own shader you&#039;ll need to pass your own uniforms<br/> Any uniform has to be declared in the material definition file in the &quot;MaterialParameters&quot; section.<br/></p><pre> MaterialParameters &#123;
&#125;</pre>
<p>
For more information on JME3 material system, i suggest you read this <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/jmonkeyengine3-material-system-full-explanation"><param name="text" value="<html><u>topic</u></html>"><param name="textColor" value="blue"></object>.<br/>
<br/>
</p>
</div>
<h3><a>JME3 Global uniforms</a></h3>
<div>
<p>
JME3 can expose pre-computed global uniforms to your shaders. You must specify the one that are required for your shader in the WorldParameters section of the material definition file (.j3md).<br/>
Note that in the shader the uniform names will be prefixed by a “g_”.<br/>
In the example above, WorldViewProjectionMatrix is declared as uniform mat4 g_WorldViewProjectionMatrix in the shader.<br/>
The complete list of global uniforms that can be used in JME3 can be found <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/shader/UniformBinding.java"><param name="text" value="<html><u>here</u></html>"><param name="textColor" value="blue"></object>.<br/>
<br/>
</p>
</div>
<h3><a>JME3 attributes</a></h3>
<div>
<p>
Those are different attributes that are always passed to your shader.<br/>
you can find a complete list of those attribute in the Type enum of the VertexBuffer <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/VertexBuffer.java"><param name="text" value="<html><u>here</u></html>"><param name="textColor" value="blue"></object>.<br/>
Note that in the shader the attributes names will be prefixed by a “in”.<br/>
<br/>
</p>
</div>
<h3><a>User&#039;s uniforms</a></h3>
<div>
<p>
At some point when making your own shader you&#039;ll need to pass your own uniforms<br/>
Any uniform has to be declared in the material definition file in the &quot;MaterialParameters&quot; section.<br/>
</p>
<pre> MaterialParameters &#123;
Vector4 Color
&#125;</pre><p> This material parameter will be sent from the engine to the shader as follow</p><pre> material.setColor&#40;&quot;Color&quot;, ColorRGBA&#40;1.0f, 0.0f, 0.0f, 1.0f&#41;;//red color</pre><p> Note that there is a setXXXX method for any type of uniform you want to pass.<br/> To use this uniform in the shader, you need to declare it in the .frag or in the .vert files (depending on where you need it) as follow :</p><pre> uniform vec4 m_Color;</pre><p> <strong>Note the &quot;m_&quot; prefix that specifies that the uniform is a material parameter.</strong><br/> This uniform will be populated at runtime with the value you sent.</p></div><h3><a
name="step_by_step">Step by step</a></h3><div
class="level3"><ul><li
class="level1"><div
class="li"> Create a vertex shader (.vert) file</div></li><li
class="level1"><div
class="li"> Create a fragment shader (.frag) file</div></li><li
class="level1"><div
class="li"> Create a material definition (j3md) file specifying the user defined uniforms, path to the shaders and the global uniforms to use</div></li><li
class="level1"><div
class="li"> In your initSimpleApplication, create a material using this definition, apply it to a geometry</div></li><li
class="level1"><div
class="li"> That’s it!!</div></li></ul><pre> // A cube
&#125;</pre>
<p>
This material parameter will be sent from the engine to the shader as follow
</p>
<pre> material.setColor&#40;&quot;Color&quot;, new ColorRGBA&#40;1.0f, 0.0f, 0.0f, 1.0f&#41;;//red color</pre>
<p>
Note that there is a setXXXX method for any type of uniform you want to pass.<br/>
To use this uniform in the shader, you need to declare it in the .frag or in the .vert files (depending on where you need it) as follow :
</p>
<pre> uniform vec4 m_Color;</pre>
<p>
<strong>Note the &quot;m_&quot; prefix that specifies that the uniform is a material parameter.</strong><br/>
This uniform will be populated at runtime with the value you sent.
</p>
</div>
<h3><a>Step by step</a></h3>
<div>
<ul>
<li><div> Create a vertex shader (.vert) file</div>
</li>
<li><div> Create a fragment shader (.frag) file</div>
</li>
<li><div> Create a material definition (j3md) file specifying the user defined uniforms, path to the shaders and the global uniforms to use</div>
</li>
<li><div> In your initSimpleApplication, create a material using this definition, apply it to a geometry</div>
</li>
<li><div> That’s it!!</div>
</li>
</ul>
<pre> // A cube
Box&#40;Vector3f.ZERO, 1f,1f,1f&#41;;
Geometry cube = new Geometry&#40;&quot;box&quot;, box&#41;;
Material mat = new Material&#40;assetManager,&quot;Path/To/My/materialDef.j3md&quot;&#41;;
cube.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;cube&#41;;</pre><p> <br/></p></div><h3><a
name="jme3_and_opengl_3_4_compatibility">JME3 and OpenGL 3 &amp; 4 compatibility</a></h3><div
class="level3"><p> GLSL 1.0 to 1.2 comes with build in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc…).<br/> Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uniforms and attributes. Here is a list of deprecated attributes and their equivalent in JME3<br/></p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">GLSL 1.2 attributes</th><th
class="col1">JME3 equivalent</th></tr><tr
class="row1"><td
class="col0 leftalign">gl_Vertex</td><td
class="col1">inPosition</td></tr><tr
class="row2"><td
class="col0 leftalign">gl_Normal</td><td
class="col1">inNormal</td></tr><tr
class="row3"><td
class="col0 leftalign">gl_Color</td><td
class="col1">inColor</td></tr><tr
class="row4"><td
class="col0 leftalign">gl_MultiTexCoord0</td><td
class="col1">inTexCoord</td></tr><tr
class="row5"><td
class="col0 leftalign">gl_ModelViewMatrix</td><td
class="col1">g_WorldViewMatrix</td></tr><tr
class="row6"><td
class="col0 leftalign">gl_ProjectionMatrix</td><td
class="col1">g_ProjectionMatrix</td></tr><tr
class="row7"><td
class="col0 leftalign">gl_ModelViewProjectionMatrix</td><td
class="col1">g_WorldViewProjectionMatrix</td></tr><tr
class="row8"><td
class="col0 leftalign">gl_NormalMatrix</td><td
class="col1">g_NormalMatrix</td></tr></table></div></div><h3><a
name="useful_links">Useful links</a></h3><div
class="level3"><p> <a
href="http://www.eng.utah.edu/~cs5610/lectures/GLSL-ATI-Intro.pdf">http://www.eng.utah.edu/~cs5610/lectures/GLSL-ATI-Intro.pdf</a></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:jme3_shaders?do=export_xhtmlbody">view online version</a></em></p>
rootNode.attachChild&#40;cube&#41;;</pre>
<p>
<br/>
</p>
</div>
<h3><a>JME3 and OpenGL 3 &amp; 4 compatibility</a></h3>
<div>
<p>
GLSL 1.0 to 1.2 comes with build in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc…).<br/>
Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uniforms and attributes. Here is a list of deprecated attributes and their equivalent in JME3<br/>
</p>
<div><table>
<tr>
<th>GLSL 1.2 attributes</th><th>JME3 equivalent</th>
</tr>
<tr>
<td>gl_Vertex </td><td>inPosition</td>
</tr>
<tr>
<td>gl_Normal </td><td>inNormal</td>
</tr>
<tr>
<td>gl_Color </td><td>inColor</td>
</tr>
<tr>
<td>gl_MultiTexCoord0 </td><td>inTexCoord</td>
</tr>
<tr>
<td>gl_ModelViewMatrix </td><td>g_WorldViewMatrix</td>
</tr>
<tr>
<td>gl_ProjectionMatrix </td><td>g_ProjectionMatrix</td>
</tr>
<tr>
<td>gl_ModelViewProjectionMatrix </td><td>g_WorldViewProjectionMatrix</td>
</tr>
<tr>
<td>gl_NormalMatrix </td><td>g_NormalMatrix</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [8076-8387] -->
</div>
<h3><a>Useful links</a></h3>
<div>
<p>
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.eng.utah.edu/~cs5610/lectures/GLSL-ATI-Intro.pdf"><param name="text" value="<html><u>http://www.eng.utah.edu/~cs5610/lectures/GLSL-ATI-Intro.pdf</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:jme3_shaders?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@ -1,32 +1,93 @@
<h1><a
name="light_and_shadow">Light and Shadow</a></h1><div
class="level1"><p> Lighting means that an object is brighter on the side facing the light direction, and darker on the backside. A light source with a direction or location is required for lit Materials to be visible. Lighting does not automatically mean that objects cast a shadow on the floor or other objects: Activating shadow processing is an extra step described below. <a
href="/wiki/lib/exe/detail.php/jme3:advanced:light-sources.png?id=jme3%3Aadvanced%3Alight_and_shadow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-sources.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:pssm.png?id=jme3%3Aadvanced%3Alight_and_shadow"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/pssm.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a></p></div><h2><a
name="light_sources">Light Sources</a></h2><div
class="level2"><p> You can add several light sources to a scene using <code>rootNode.addLight()</code>. All Lighting.j3md- based Materials require a light source to be visible.
The available light sources in <code>com.jme3.light</code> are SpotLight, PointLight, AmbientLight, and DirectionalLight. You can set the color of the light – normally, it is white. You can choose to set other colors to influence the scene&#039;s atmosphere.
A PointLight has a location and shines from there in all directions as far as its radius reaches, like a lamp. The light intensity decreases with increased distance from the light source.</p><pre>PointLight lamp_light = new PointLight&#40;&#41;;
<h1><a>Light and Shadow</a></h1>
<div>
<p>
Lighting means that an object is brighter on the side facing the light direction, and darker on the backside. A light source with a direction or location is required for lit Materials to be visible. Lighting does not automatically mean that objects cast a shadow on the floor or other objects: Activating shadow processing is an extra step described below.
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/light-sources.png"> <img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/pssm.png">
</p>
</div>
<h2><a>Light Sources</a></h2>
<div>
<p>
You can add several light sources to a scene using <code>rootNode.addLight()</code>. All Lighting.j3md- based Materials require a light source to be visible.
The available light sources in <code>com.jme3.light</code> are SpotLight (<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/graphics/forum/topic/will-pay-for-cone-light-implementation/"><param name="text" value="<html><u>WIP</u></html>"><param name="textColor" value="blue"></object>), PointLight, AmbientLight, and DirectionalLight. You can set the color (intensity) of the light – normally, it is white (ColorRGBA(1,1,1,1)). You can choose to set other colors to influence the scene&#039;s atmosphere.
A PointLight has a location and shines from there in all directions as far as its radius reaches, like a lamp. The light intensity decreases with increased distance from the light source.
</p>
<pre>PointLight lamp_light = new PointLight&#40;&#41;;
lamp_light.setColor&#40;ColorRGBA.Yellow&#41;;
lamp_light.setRadius&#40;4f&#41;;
lamp_light.setPosition&#40;new Vector3f&#40;lamp_geo.getLocalTranslation&#40;&#41;&#41;&#41;;
rootNode.addLight&#40;lamp_light&#41;;</pre><p> A DirectionalLight has no position, only a direction. It is considered &quot;infinitely&quot; far away and sends out parallel beams of light. It can cast shadows. You typically use it to simulate sun light:</p><pre>DirectionalLight sun = new DirectionalLight&#40;&#41;;
rootNode.addLight&#40;lamp_light&#41;;</pre>
<p>
A DirectionalLight has no position, only a direction. It is considered &quot;infinitely&quot; far away and sends out parallel beams of light. It can cast shadows. You typically use it to simulate sun light:
</p>
<pre>DirectionalLight sun = new DirectionalLight&#40;&#41;;
sun.setColor&#40;ColorRGBA.White&#41;;
sun.setDirection&#40;new Vector3f&#40;-1, -1, -1&#41;.normalizeLocal&#40;&#41;&#41;;
rootNode.addLight&#40;sun&#41;;</pre><p> An AmbientLight influences the brightness of the whole scene globally. It has no direction and no location, and does not cast any shadow.</p><pre>AmbientLight al = new AmbientLight&#40;&#41;;
sun.setDirection&#40;new Vector3f&#40;-1,13, -1,13, 1,13&#41;.normalizeLocal&#40;&#41;&#41;;
rootNode.addLight&#40;sun&#41;;</pre>
<p>
An AmbientLight influences the brightness of the scene globally. It has no direction and no location, and does not cast any shadows.
</p>
<pre>AmbientLight al = new AmbientLight&#40;&#41;;
al.setColor&#40;ColorRGBA.White.mult&#40;1.3f&#41;&#41;;
rootNode.addLight&#40;al&#41;;</pre><p> A SpotLight is like a flashlight that sends a distinct beam of light. (Still work in progress, as of alpha-3.)</p></div><h2><a
name="simple_lighting">Simple Lighting</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestSimpleLighting.java">TestSimpleLighting.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestLightRadius.java">TestLightRadius.java</a></div></li></ul><p> Here we use a material based on Lighting.j3md (<a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">More info about Materials</a>). Lighting.j3md-based materials dynamically support Shininess, and Ambient, Diffuse, and Specular Colors.</p><pre>Geometry teapot = &#40;Geometry&#41; assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;
rootNode.addLight&#40;al&#41;;</pre>
<p>
A SpotLight is like a flashlight that sends a distinct beam, or cone of light. A SpotLight has a direction, a position, distance (range) and an angle. The inner angle is the central maximum of the light cone, the outer angle the edge of the light cone. Everything outside the light cone&#039;s angles is not affacted by the light.
</p>
<pre>SpotLight sl = new SpotLight&#40;&#41;;
sl.setDirection&#40;new Vector3f&#40;1,0,1&#41;&#41;; // direction
sl.setPosition&#40;new Vector3f&#40;0,0,0&#41;&#41;;
sl.setSpotInnerAngle&#40;15f&#41;; // inner light cone (maximum)
sl.setSpotOuterAngle&#40;35f&#41;; // outer light cone (edge of the light)
sl.setSpotRange&#40;10f&#41;; // distance
sl.setColor&#40;ColorRGBA.White.mult&#40;1.3f&#41;&#41;;
rootNode.addLight&#40;sl&#41;;</pre>
</div>
<h2><a>LightControl</a></h2>
<div>
<p>
You can use a com.jme3.scene.control.LightControl to make a SpotLight or PointLight follow a Spatial.
</p>
<pre> PointLight myLight = new PointLight&#40;&#41;;
rootNode.addLight&#40;myLight&#41;;
LightControl lightControl = new LightControl&#40;myLight&#41;;
spatial.addControl&#40;lightControl&#41;;</pre>
</div>
<h2><a>Simple Lighting</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestSimpleLighting.java"><param name="text" value="<html><u>TestSimpleLighting.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestLightRadius.java"><param name="text" value="<html><u>TestLightRadius.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
Here we use a material based on Lighting.j3md (<a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">More info about Materials</a>). Lighting.j3md-based materials dynamically support Shininess, and Ambient, Diffuse, and Specular Colors.
</p>
<pre>Geometry teapot = &#40;Geometry&#41; assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;
TangentBinormalGenerator.generate&#40;teapot.getMesh&#40;&#41;, true&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Light/Lighting.j3md&quot;&#41;;
mat.setBoolean&#40;&quot;m_UseMaterialColors&quot;, true&#41;;
@ -34,7 +95,14 @@ mat.setColor&#40;&quot;m_Ambient&quot;, ColorRGBA.Black&#41;;
mat.setColor&#40;&quot;m_Diffuse&quot;, ColorRGBA.Blue&#41;;
mat.setColor&#40;&quot;m_Specular&quot;, ColorRGBA.White&#41;;
mat.setFloat&#40;&quot;m_Shininess&quot;, 12&#41;;
rootNode.attachChild&#40;teapot&#41;;</pre><p> In this example, we use material colors instead of textures. But you can equally well use Lighting.j3md to create a Material that uses texture maps, such as the Diffuse and Normal map used here, but also Specular and Paralax Maps:</p><pre> Sphere rock = new Sphere&#40;32,32, 2f&#41;;
rootNode.attachChild&#40;teapot&#41;;</pre>
<p>
In this example, we use material colors instead of textures. But you can equally well use Lighting.j3md to create a Material that uses texture maps, such as the Diffuse and Normal map used here, but also Specular and Paralax Maps:
</p>
<pre> Sphere rock = new Sphere&#40;32,32, 2f&#41;;
Geometry shiny_rock = new Geometry&#40;&quot;Shiny rock&quot;, rock&#41;;
rock.setTextureMode&#40;Sphere.TextureMode.Projected&#41;; // better quality on spheres
TangentBinormalGenerator.generate&#40;rock&#41;; // for lighting effect
@ -46,14 +114,30 @@ rootNode.attachChild&#40;teapot&#41;;</pre><p> In this example, we use material
assetManager.loadTexture&#40;&quot;Textures/Terrain/Pond/Pond_normal.png&quot;&#41;&#41;;
mat_lit.setFloat&#40;&quot;m_Shininess&quot;, 5f&#41;; // [0,128]
shiny_rock.setMaterial&#40;mat_lit&#41;;
rootNode.attachChild&#40;shiny_rock&#41;;</pre><p> This lighting updates live when the object or light source moves. If you shine a colored PointLight at this object, you will see a light reflection in the color of the PointLight.
This lighting method doesn&#039;t make the node cast a shadow onto other nodes.</p></div><h2><a
name="basicshadowrenderer">BasicShadowRenderer</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestShadow.java">TestShadow.java</a></div></li></ul><p> Use the Shadow Renderer to make textured scene nodes cast and receive shadows.
Switch off the default shadow mode, and add a jME SceneProcessor named com.jme3.shadow.BasicShadowRenderer to the viewPort.</p><pre>BasicShadowRenderer bsr;
rootNode.attachChild&#40;shiny_rock&#41;;</pre>
<p>
This lighting updates live when the object or light source moves. If you shine a colored PointLight at this object, you will see a light reflection in the color of the PointLight.
This lighting method doesn&#039;t make the node cast a shadow onto other nodes.
</p>
</div>
<h2><a>BasicShadowRenderer</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestShadow.java"><param name="text" value="<html><u>TestShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
Use the Shadow Renderer to make textured scene nodes cast and receive shadows.
Switch off the default shadow mode, and add a jME SceneProcessor named com.jme3.shadow.BasicShadowRenderer to the viewPort.
</p>
<pre>BasicShadowRenderer bsr;
...
public void simpleInitApp&#40;&#41; &#123;
...
@ -61,49 +145,89 @@ public void simpleInitApp&#40;&#41; &#123;
bsr = new BasicShadowRenderer&#40;assetManager, 256&#41;;
bsr.setDirection&#40;new Vector3f&#40;-1, -1, -1&#41;.normalizeLocal&#40;&#41;&#41;;
viewPort.addProcessor&#40;bsr&#41;;
...</pre><p> For every scene node that needs shadows, individually specify the shadow behaviour: Whether it cast shadows, receive shadows, both, or neither.</p><pre>wall.setShadowMode&#40;ShadowMode.CastAndReceive&#41;;
...</pre>
<p>
For every scene node that needs shadows, individually specify the shadow behaviour: Whether it cast shadows, receive shadows, both, or neither.
</p>
<pre>wall.setShadowMode&#40;ShadowMode.CastAndReceive&#41;;
...
floor.setShadowMode&#40;ShadowMode.Receive&#41;;
...
airplane.setShadowMode&#40;ShadowMode.Cast&#41;;
...
ghost.setShadowMode&#40;ShadowMode.Off&#41;;
...</pre></div><h2><a
name="parallel-split_shadow_map">Parallel-Split Shadow Map</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java">TestPssmShadow.java</a></div></li></ul><p> The PSSM shadow renderer can cast real-time shadows on curved surfaces.
To activate it, add a jME SceneProcessor named <code>com.jme3.shadow.PssmShadowRenderer</code> to the viewPort.</p><pre>private PssmShadowRenderer pssmRenderer;
...</pre>
</div>
<h2><a>Parallel-Split Shadow Map</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/light/TestPssmShadow.java"><param name="text" value="<html><u>TestPssmShadow.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
The PSSM shadow renderer can cast real-time shadows on curved surfaces.
To activate it, add a jME SceneProcessor named <code>com.jme3.shadow.PssmShadowRenderer</code> to the viewPort.
</p>
<pre>private PssmShadowRenderer pssmRenderer;
...
public void simpleInitApp&#40;&#41; &#123;
....
pssmRenderer = new PssmShadowRenderer&#40;
assetManager,1024,4,PssmShadowRenderer.EDGE_FILTERING_PCF&#41;;
pssmRenderer.setDirection&#40;new Vector3f&#40;-1, -1, -1&#41;.normalizeLocal&#40;&#41;&#41;;
viewPort.addProcessor&#40;pssmRenderer&#41;;</pre><p> The constructor expects the following values:</p><ul><li
class="level1"><div
class="li"> Your assetManager object</div></li><li
class="level1"><div
class="li"> The size of the rendered shadowmaps (512, 1024, 2048, etc…)</div></li><li
class="level1"><div
class="li"> The number of shadow maps rendered (the more shadow maps, the more quality, the less FPS).</div></li><li
class="level1"><div
class="li"> The type of filtering for shadow edge smoothing:</div><ul><li
class="level2"><div
class="li"> PSSMShadowRenderer.EDGE_FILTERING_DITHER</div></li><li
class="level2"><div
class="li"> PSSMShadowRenderer.EDGE_FILTERING_PCF (default).</div></li></ul></li></ul><p> You can set the following properties on the <code>pssmRenderer</code> object:</p><ul><li
class="level1"><div
class="li"> setDirection(Vector3f) – the direction of the light</div></li><li
class="level1"><div
class="li"> setLambda(0.65f) – Factor to use to reduce the split size</div></li><li
class="level1"><div
class="li"> setShadowIntensity(0.7f) – shadow darkness (1 black, 0 invisible)</div></li><li
class="level1"><div
class="li"> setShadowZextend() – distance how far away from camera shadows will still be computed</div></li></ul><p> As usual, specify the shadow behaviour for every scene node.</p><pre>...
viewPort.addProcessor&#40;pssmRenderer&#41;;</pre>
<p>
The constructor expects the following values:
</p>
<ul>
<li><div> Your assetManager object</div>
</li>
<li><div> The size of the rendered shadowmaps (512, 1024, 2048, etc…)</div>
</li>
<li><div> The number of shadow maps rendered (the more shadow maps, the more quality, the less FPS).</div>
</li>
<li><div> The type of filtering for shadow edge smoothing:</div>
<ul>
<li><div> PSSMShadowRenderer.EDGE_FILTERING_DITHER</div>
</li>
<li><div> PSSMShadowRenderer.EDGE_FILTERING_PCF (default).</div>
</li>
</ul>
</li>
</ul>
<p>
You can set the following properties on the <code>pssmRenderer</code> object:
</p>
<ul>
<li><div> setDirection(Vector3f) – the direction of the light</div>
</li>
<li><div> setLambda(0.65f) – Factor to use to reduce the split size</div>
</li>
<li><div> setShadowIntensity(0.7f) – shadow darkness (1 black, 0 invisible)</div>
</li>
<li><div> setShadowZextend() – distance how far away from camera shadows will still be computed</div>
</li>
</ul>
<p>
As usual, specify the shadow behaviour for every scene node.
</p>
<pre>...
teapot.setShadowMode&#40;ShadowMode.CastAndReceive&#41;;
...
soil.setShadowMode&#40;ShadowMode.Receive&#41;;
...</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:light_and_shadow?do=export_xhtmlbody">view online version</a></em></p>
...</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:light_and_shadow?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,572 @@
<h3><a>Nifty Loading Screen (Progress Bar)</a></h3>
<div>
<p>
There is a good tutorial about creating a nifty progress bar here:
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Create_your_own_Control_%28A_Nifty_Progressbar%29"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Create_your_own_Control_%28A_Nifty_Progressbar%29</u></html>"><param name="textColor" value="blue"></object>
</p>
<p>
This example will the existing hello terrain as an example.
It will require these 2 images inside Assets/Interface/ (save them as border.png and inner.png respectively)
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/inner1.png">
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/border1.png">
</p>
<p>
This is the progress bar at 90%:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/loadingscreen.png">
</p>
<p>
nifty_loading.xml
</p>
<pre><span>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span><span>&lt;nifty&gt;</span></span>
<span>&lt;useStyles filename=&quot;nifty-default-styles.xml&quot; /&gt;</span>
<span>&lt;useControls filename=&quot;nifty-default-controls.xml&quot; /&gt;</span>
&nbsp;
<span>&lt;controlDefinition name = &quot;loadingbar&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;image filename=&quot;Interface/border.png&quot; childLayout=&quot;absolute&quot; </span>
<span> imageMode=&quot;resize:15,2,15,15,15,2,15,2,15,2,15,15&quot;&gt;</span>
<span>&lt;image id=&quot;progressbar&quot; x=&quot;0&quot; y=&quot;0&quot; filename=&quot;Interface/inner.png&quot; width=&quot;32px&quot; height=&quot;100%&quot;</span>
<span> imageMode=&quot;resize:15,2,15,15,15,2,15,2,15,2,15,15&quot; /&gt;</span>
<span><span>&lt;/image&gt;</span></span>
<span><span>&lt;/controlDefinition&gt;</span></span>
&nbsp;
<span>&lt;screen id=&quot;start&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;layer id=&quot;layer&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;panel id = &quot;panel2&quot; height=&quot;30%&quot; width=&quot;50%&quot; align=&quot;center&quot; valign=&quot;center&quot; childLayout=&quot;vertical&quot;</span>
<span> visibleToMouse=&quot;true&quot;&gt;</span>
<span>&lt;control id=&quot;startGame&quot; name=&quot;button&quot; backgroundColor=&quot;#0000&quot; label=&quot;Load Game&quot; align=&quot;center&quot;&gt;</span>
<span>&lt;interact onClick=&quot;showLoadingMenu()&quot; /&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span>
&nbsp;
<span>&lt;screen id=&quot;loadlevel&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;layer id=&quot;loadinglayer&quot; childLayout=&quot;center&quot; backgroundColor=&quot;#000000&quot;&gt;</span>
<span>&lt;panel id = &quot;loadingpanel&quot; childLayout=&quot;vertical&quot; align=&quot;center&quot; valign=&quot;center&quot; height=&quot;32px&quot; width=&quot;400px&quot;&gt;</span>
<span>&lt;control name=&quot;loadingbar&quot; align=&quot;center&quot; valign=&quot;center&quot; width=&quot;400px&quot; height=&quot;32px&quot; /&gt;</span>
<span>&lt;control id=&quot;loadingtext&quot; name=&quot;label&quot; align=&quot;center&quot; </span>
<span> text=&quot; &quot;/&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span>
&nbsp;
<span>&lt;screen id=&quot;end&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span><span>&lt;/screen&gt;</span></span>
&nbsp;
<span><span>&lt;/nifty&gt;</span></span></pre>
</div>
<h4><a>Understanding Nifty XML</a></h4>
<div>
<p>
The progress bar and text is done statically using nifty <acronym title="Extensible Markup Language">XML</acronym>.
A custom control is created, which represents the progress bar.
</p>
<pre> <span>&lt;controlDefinition name = &quot;loadingbar&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;image filename=&quot;Interface/border.png&quot; childLayout=&quot;absolute&quot; </span>
<span> imageMode=&quot;resize:15,2,15,15,15,2,15,2,15,2,15,15&quot;&gt;</span>
<span>&lt;image id=&quot;progressbar&quot; x=&quot;0&quot; y=&quot;0&quot; filename=&quot;Interface/inner.png&quot; width=&quot;32px&quot; height=&quot;100%&quot;</span>
<span> imageMode=&quot;resize:15,2,15,15,15,2,15,2,15,2,15,15&quot;/&gt;</span>
<span><span>&lt;/image&gt;</span></span>
<span><span>&lt;/controlDefinition&gt;</span></span></pre>
<p>
This screen simply displays a button in the middle of the screen, which could be seen as a simple main menu UI.
</p>
<pre> <span>&lt;screen id=&quot;start&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;layer id=&quot;layer&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;panel id = &quot;panel2&quot; height=&quot;30%&quot; width=&quot;50%&quot; align=&quot;center&quot; valign=&quot;center&quot; childLayout=&quot;vertical&quot;</span>
<span> visibleToMouse=&quot;true&quot;&gt;</span>
<span>&lt;control id=&quot;startGame&quot; name=&quot;button&quot; backgroundColor=&quot;#0000&quot; label=&quot;Load Game&quot; align=&quot;center&quot;&gt;</span>
<span>&lt;interact onClick=&quot;showLoadingMenu()&quot; /&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span></pre>
<p>
This screen displays our custom progress bar control with a text control
</p>
<pre> <span>&lt;screen id=&quot;loadlevel&quot; controller = &quot;jme3test.TestLoadingScreen&quot;&gt;</span>
<span>&lt;layer id=&quot;loadinglayer&quot; childLayout=&quot;center&quot; backgroundColor=&quot;#000000&quot;&gt;</span>
<span>&lt;panel id = &quot;loadingpanel&quot; childLayout=&quot;vertical&quot; align=&quot;center&quot; valign=&quot;center&quot; height=&quot;32px&quot; width=&quot;400px&quot;&gt;</span>
<span>&lt;control name=&quot;loadingbar&quot; align=&quot;center&quot; valign=&quot;center&quot; width=&quot;400px&quot; height=&quot;32px&quot; /&gt;</span>
<span>&lt;control id=&quot;loadingtext&quot; name=&quot;label&quot; align=&quot;center&quot;</span>
<span> text=&quot; &quot;/&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span></pre>
</div>
<h3><a>Creating the bindings to use the Nifty XML</a></h3>
<div>
<p>
There are 3 main ways to update a progress bar. To understand why these methods are necessary, an understanding of the graphics pipeline is needed.
</p>
<p>
Something like this in a single thread will not work:
</p>
<pre>load_scene&#40;&#41;;
update_bar&#40;30%&#41;;
load_characters&#40;&#41;;
update_bar&#40;60%&#41;;
load_sounds&#40;&#41;;
update_bar&#40;100%&#41;;</pre>
<p>
If you do all of this in a single frame, then it is sent to the graphics card only after the whole code block has executed. By this time the bar has reached 100% and the game has already begun – for the user, the progressbar on the screen would not have visibly changed.
</p>
<p>
The 3 main good solutions are:
</p>
<ol>
<li><div> Updating explicitly over many frames</div>
</li>
<li><div> Multi-threading</div>
</li>
<li><div> Using a custom AppState</div>
</li>
</ol>
</div>
<h4><a>Updating progress bar over a number of frames</a></h4>
<div>
<p>
The idea is to break down the loading of the game into discrete parts
</p>
<pre>package jme3test;
&nbsp;
import com.jme3.niftygui.NiftyJmeDisplay;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.tools.SizeValue;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.renderer.Camera;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import de.lessvoid.nifty.controls.Controller;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.xml.xpp3.Attributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import jme3tools.converters.ImageToAwt;
&nbsp;
public class TestLoadingScreen extends SimpleApplication implements ScreenController, Controller &#123;
&nbsp;
private NiftyJmeDisplay niftyDisplay;
private Nifty nifty;
private Element progressBarElement;
private TerrainQuad terrain;
private Material mat_terrain;
private float frameCount = 0;
private boolean load = false;
private TextRenderer textRenderer;
&nbsp;
public static void main&#40;String&#91;&#93; args&#41; &#123;
TestLoadingScreen app = new TestLoadingScreen&#40;&#41;;
app.start&#40;&#41;;
&#125;
&nbsp;
@Override
public void simpleInitApp&#40;&#41; &#123;
flyCam.setEnabled&#40;false&#41;;
niftyDisplay = new NiftyJmeDisplay&#40;assetManager,
inputManager,
audioRenderer,
guiViewPort&#41;;
nifty = niftyDisplay.getNifty&#40;&#41;;
&nbsp;
nifty.fromXml&#40;&quot;Interface/nifty_loading.xml&quot;, &quot;start&quot;, this&#41;;
&nbsp;
guiViewPort.addProcessor&#40;niftyDisplay&#41;;
&#125;
&nbsp;
@Override
public void simpleUpdate&#40;float tpf&#41; &#123;
&nbsp;
if &#40;load == true&#41; &#123; //loading is done over many frames
if &#40;frameCount == 1&#41; &#123;
Element element = nifty.getScreen&#40;&quot;loadlevel&quot;&#41;.findElementByName&#40;&quot;loadingtext&quot;&#41;;
textRenderer = element.getRenderer&#40;TextRenderer.class&#41;;
&nbsp;
mat_terrain = new Material&#40;assetManager, &quot;Common/MatDefs/Terrain/Terrain.j3md&quot;&#41;;
mat_terrain.setTexture&#40;&quot;Alpha&quot;, assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/alphamap.png&quot;&#41;&#41;;
setProgress&#40;0.2f, &quot;Loading grass&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 2&#41; &#123;
Texture grass = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/grass.jpg&quot;&#41;;
grass.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex1&quot;, grass&#41;;
mat_terrain.setFloat&#40;&quot;Tex1Scale&quot;, 64f&#41;;
setProgress&#40;0.4f, &quot;Loading dirt&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 3&#41; &#123;
Texture dirt = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/dirt.jpg&quot;&#41;;
&nbsp;
dirt.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex2&quot;, dirt&#41;;
mat_terrain.setFloat&#40;&quot;Tex2Scale&quot;, 32f&#41;;
setProgress&#40;0.5f, &quot;Loading rocks&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 4&#41; &#123;
Texture rock = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/road.jpg&quot;&#41;;
&nbsp;
rock.setWrap&#40;WrapMode.Repeat&#41;;
&nbsp;
mat_terrain.setTexture&#40;&quot;Tex3&quot;, rock&#41;;
mat_terrain.setFloat&#40;&quot;Tex3Scale&quot;, 128f&#41;;
setProgress&#40;0.6f, &quot;Creating terrain&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 5&#41; &#123;
AbstractHeightMap heightmap = null;
Texture heightMapImage = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/mountains512.png&quot;&#41;;
heightmap = new ImageBasedHeightMap&#40;
ImageToAwt.convert&#40;heightMapImage.getImage&#40;&#41;, false, true, 0&#41;&#41;;
&nbsp;
heightmap.load&#40;&#41;;
terrain = new TerrainQuad&#40;&quot;my terrain&quot;, 65, 513, heightmap.getHeightMap&#40;&#41;&#41;;
setProgress&#40;0.8f, &quot;Positioning terrain&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 6&#41; &#123;
terrain.setMaterial&#40;mat_terrain&#41;;
&nbsp;
terrain.setLocalTranslation&#40;0, -100, 0&#41;;
terrain.setLocalScale&#40;2f, 1f, 2f&#41;;
rootNode.attachChild&#40;terrain&#41;;
setProgress&#40;0.9f, &quot;Loading cameras&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 7&#41; &#123;
List&lt;Camera&gt; cameras = new ArrayList&lt;Camera&gt;&#40;&#41;;
cameras.add&#40;getCamera&#40;&#41;&#41;;
TerrainLodControl control = new TerrainLodControl&#40;terrain, cameras&#41;;
terrain.addControl&#40;control&#41;;
setProgress&#40;1f, &quot;Loading complete&quot;&#41;;
&nbsp;
&#125; else if &#40;frameCount == 8&#41; &#123;
nifty.gotoScreen&#40;&quot;end&quot;&#41;;
nifty.exit&#40;&#41;;
guiViewPort.removeProcessor&#40;niftyDisplay&#41;;
flyCam.setEnabled&#40;true&#41;;
flyCam.setMoveSpeed&#40;50&#41;;
&#125;
&nbsp;
frameCount++;
&#125;
&#125;
&nbsp;
public void setProgress&#40;final float progress, String loadingText&#41; &#123;
final int MIN_WIDTH = 32;
int pixelWidth = &#40;int&#41; &#40;MIN_WIDTH + &#40;progressBarElement.getParent&#40;&#41;.getWidth&#40;&#41; - MIN_WIDTH&#41; * progress&#41;;
progressBarElement.setConstraintWidth&#40;new SizeValue&#40;pixelWidth + &quot;px&quot;&#41;&#41;;
progressBarElement.getParent&#40;&#41;.layoutElements&#40;&#41;;
&nbsp;
textRenderer.setText&#40;loadingText&#41;;
&#125;
&nbsp;
public void showLoadingMenu&#40;&#41; &#123;
nifty.gotoScreen&#40;&quot;loadlevel&quot;&#41;;
load = true;
&#125;
&nbsp;
@Override
public void onStartScreen&#40;&#41; &#123;
&#125;
&nbsp;
@Override
public void onEndScreen&#40;&#41; &#123;
&#125;
&nbsp;
@Override
public void bind&#40;Nifty nifty, Screen screen&#41; &#123;
progressBarElement = nifty.getScreen&#40;&quot;loadlevel&quot;&#41;.findElementByName&#40;&quot;progressbar&quot;&#41;;
&#125;
&nbsp;
// methods for Controller
@Override
public boolean inputEvent&#40;final NiftyInputEvent inputEvent&#41; &#123;
return false;
&#125;
&nbsp;
@Override
public void bind&#40;Nifty nifty, Screen screen, Attributes atrbts&#41; &#123;
progressBarElement = elmnt.findElementByName&#40;&quot;progressbar&quot;&#41;;
&#125;
&nbsp;
@Override
public void init&#40;Attributes atrbts&#41; &#123;
&#125;
&nbsp;
public void onFocus&#40;boolean getFocus&#41; &#123;
&#125;
&#125;</pre>
<p>
Note:
</p>
<ul>
<li><div> Try and add all controls near the end, as their update loops may begin executing</div>
</li>
</ul>
</div>
<h4><a>Using multithreading</a></h4>
<div>
<p>
For more info on multithreading: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading"><param name="text" value="<html><u>http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading</u></html>"><param name="textColor" value="blue"></object>
</p>
<p>
Make sure to change the <acronym title="Extensible Markup Language">XML</acronym> file to point the controller to TestLoadingScreen<strong>1</strong>
</p>
<pre>package jme3test;
&nbsp;
import com.jme3.niftygui.NiftyJmeDisplay;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.tools.SizeValue;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.renderer.Camera;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import de.lessvoid.nifty.controls.Controller;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.xml.xpp3.Attributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import jme3tools.converters.ImageToAwt;
&nbsp;
public class TestLoadingScreen1 extends SimpleApplication implements ScreenController, Controller &#123;
&nbsp;
private NiftyJmeDisplay niftyDisplay;
private Nifty nifty;
private Element progressBarElement;
private TerrainQuad terrain;
private Material mat_terrain;
private boolean load = false;
private ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor&#40;2&#41;;
private Future loadFuture = null;
private TextRenderer textRenderer;
&nbsp;
public static void main&#40;String&#91;&#93; args&#41; &#123;
TestLoadingScreen1 app = new TestLoadingScreen1&#40;&#41;;
app.start&#40;&#41;;
&#125;
&nbsp;
@Override
public void simpleInitApp&#40;&#41; &#123;
flyCam.setEnabled&#40;false&#41;;
niftyDisplay = new NiftyJmeDisplay&#40;assetManager,
inputManager,
audioRenderer,
guiViewPort&#41;;
nifty = niftyDisplay.getNifty&#40;&#41;;
&nbsp;
nifty.fromXml&#40;&quot;Interface/nifty_loading.xml&quot;, &quot;start&quot;, this&#41;;
&nbsp;
guiViewPort.addProcessor&#40;niftyDisplay&#41;;
&#125;
&nbsp;
@Override
public void simpleUpdate&#40;float tpf&#41; &#123;
if &#40;load&#41; &#123;
if &#40;loadFuture == null&#41; &#123;
//if we have not started loading yet, submit the Callable to the executor
loadFuture = exec.submit&#40;loadingCallable&#41;;
&#125;
//check if the execution on the other thread is done
if &#40;loadFuture.isDone&#40;&#41;&#41; &#123;
//these calls have to be done on the update loop thread,
//especially attaching the terrain to the rootNode
//after it is attached, it's managed by the update loop thread
// and may not be modified from any other thread anymore!
nifty.gotoScreen&#40;&quot;end&quot;&#41;;
nifty.exit&#40;&#41;;
guiViewPort.removeProcessor&#40;niftyDisplay&#41;;
flyCam.setEnabled&#40;true&#41;;
flyCam.setMoveSpeed&#40;50&#41;;
rootNode.attachChild&#40;terrain&#41;;
load = false;
&#125;
&#125;
&#125;
//this is the callable that contains the code that is run on the other thread.
//since the assetmananger is threadsafe, it can be used to load data from any thread
//we do *not* attach the objects to the rootNode here!
Callable&lt;Void&gt; loadingCallable = new Callable&lt;Void&gt;&#40;&#41; &#123;
&nbsp;
public Void call&#40;&#41; &#123;
&nbsp;
Element element = nifty.getScreen&#40;&quot;loadlevel&quot;&#41;.findElementByName&#40;&quot;loadingtext&quot;&#41;;
textRenderer = element.getRenderer&#40;TextRenderer.class&#41;;
&nbsp;
mat_terrain = new Material&#40;assetManager, &quot;Common/MatDefs/Terrain/Terrain.j3md&quot;&#41;;
mat_terrain.setTexture&#40;&quot;Alpha&quot;, assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/alphamap.png&quot;&#41;&#41;;
//setProgress is thread safe (see below)
setProgress&#40;0.2f, &quot;Loading grass&quot;&#41;;
&nbsp;
Texture grass = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/grass.jpg&quot;&#41;;
grass.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex1&quot;, grass&#41;;
mat_terrain.setFloat&#40;&quot;Tex1Scale&quot;, 64f&#41;;
setProgress&#40;0.4f, &quot;Loading dirt&quot;&#41;;
&nbsp;
Texture dirt = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/dirt.jpg&quot;&#41;;
&nbsp;
dirt.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex2&quot;, dirt&#41;;
mat_terrain.setFloat&#40;&quot;Tex2Scale&quot;, 32f&#41;;
setProgress&#40;0.5f, &quot;Loading rocks&quot;&#41;;
&nbsp;
Texture rock = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/road.jpg&quot;&#41;;
&nbsp;
rock.setWrap&#40;WrapMode.Repeat&#41;;
&nbsp;
mat_terrain.setTexture&#40;&quot;Tex3&quot;, rock&#41;;
mat_terrain.setFloat&#40;&quot;Tex3Scale&quot;, 128f&#41;;
setProgress&#40;0.6f, &quot;Creating terrain&quot;&#41;;
&nbsp;
AbstractHeightMap heightmap = null;
Texture heightMapImage = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/mountains512.png&quot;&#41;;
heightmap = new ImageBasedHeightMap&#40;
ImageToAwt.convert&#40;heightMapImage.getImage&#40;&#41;, false, true, 0&#41;&#41;;
&nbsp;
heightmap.load&#40;&#41;;
terrain = new TerrainQuad&#40;&quot;my terrain&quot;, 65, 513, heightmap.getHeightMap&#40;&#41;&#41;;
setProgress&#40;0.8f, &quot;Positioning terrain&quot;&#41;;
&nbsp;
terrain.setMaterial&#40;mat_terrain&#41;;
&nbsp;
terrain.setLocalTranslation&#40;0, -100, 0&#41;;
terrain.setLocalScale&#40;2f, 1f, 2f&#41;;
setProgress&#40;0.9f, &quot;Loading cameras&quot;&#41;;
&nbsp;
List&lt;Camera&gt; cameras = new ArrayList&lt;Camera&gt;&#40;&#41;;
cameras.add&#40;getCamera&#40;&#41;&#41;;
TerrainLodControl control = new TerrainLodControl&#40;terrain, cameras&#41;;
terrain.addControl&#40;control&#41;;
setProgress&#40;1f, &quot;Loading complete&quot;&#41;;
&nbsp;
return null;
&#125;
&#125;;
&nbsp;
public void setProgress&#40;final float progress, final String loadingText&#41; &#123;
//since this method is called from another thread, we enqueue the changes to the progressbar to the update loop thread
enqueue&#40;new Callable&#40;&#41; &#123;
&nbsp;
public Exception &#123;
final int MIN_WIDTH = 32;
int pixelWidth = &#40;int&#41; &#40;MIN_WIDTH + &#40;progressBarElement.getParent&#40;&#41;.getWidth&#40;&#41; - MIN_WIDTH&#41; * progress&#41;;
progressBarElement.setConstraintWidth&#40;new SizeValue&#40;pixelWidth + &quot;px&quot;&#41;&#41;;
progressBarElement.getParent&#40;&#41;.layoutElements&#40;&#41;;
&nbsp;
textRenderer.setText&#40;loadingText&#41;;
return null;
&#125;
&#125;&#41;;
&nbsp;
&#125;
&nbsp;
public void showLoadingMenu&#40;&#41; &#123;
nifty.gotoScreen&#40;&quot;loadlevel&quot;&#41;;
load = true;
&#125;
&nbsp;
@Override
public void onStartScreen&#40;&#41; &#123;
&#125;
&nbsp;
@Override
public void onEndScreen&#40;&#41; &#123;
&#125;
&nbsp;
@Override
public void bind&#40;Nifty nifty, Screen screen&#41; &#123;
progressBarElement = nifty.getScreen&#40;&quot;loadlevel&quot;&#41;.findElementByName&#40;&quot;progressbar&quot;&#41;;
&#125;
&nbsp;
// methods for Controller
@Override
public boolean inputEvent&#40;final NiftyInputEvent inputEvent&#41; &#123;
return false;
&#125;
&nbsp;
@Override
public void bind&#40;Nifty nifty, Screen screen, Attributes atrbts&#41; &#123;
progressBarElement = elmnt.findElementByName&#40;&quot;progressbar&quot;&#41;;
&#125;
&nbsp;
@Override
public void init&#40;Attributes atrbts&#41; &#123;
&#125;
&nbsp;
public void onFocus&#40;boolean getFocus&#41; &#123;
&#125;
&#125;</pre>
</div>
<h4><a>Using Appstates</a></h4>
<div>
<p>
TO DO
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:loading_screen?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -1,65 +1,180 @@
<h1><a
name="localizing_jme_3_games">Localizing jME 3 Games</a></h1><div
class="level1"></div><h2><a
name="scope">Scope</a></h2><div
class="level2"><p> Localizing an application can mean several things:</p><ul><li
class="level1"><div
class="li"> At minimum you translate all messages and dialogs in the user interface to your target languages.</div></li><li
class="level1"><div
class="li"> You should also translate the &quot;read me&quot;, help, and other documentation.</div></li><li
class="level1"><div
class="li"> Also translating web content related to the application makes sure international users find out about your localized game.</div></li><li
class="level1"><div
class="li"> If you go the whole way of internationalization, you also &quot;translate&quot; metaphors in icons or symbols used. <br/> E.g. For localizations to right-to-left languages, you must also adjust the whole flow of the UI (order of menus and buttons).</div></li></ul><p> There are tools that assist you with localizing Java Swing GUIs. jME3 applications do not typically have a Swing <acronym
title="Graphical User Interface">GUI</acronym>, so those tools are not of much help. Just stick to the normal Java rules about using Bundle Properties:</p></div><h2><a
name="preparing_the_localization">Preparing the Localization</a></h2><div
class="level2"><p> <strong>Tip:</strong> The jMonkeyPlatform supports opening and editing Bundle.properties files. Also note the Tools &gt; Localization menu.</p><p> To prepare the application for localization, you have to first identify all hard-coded messages.</p><ol><li
class="level1"><div
class="li"> Find every line in your jME3 game where you hard-coded message strings, e.g. <br/><pre>System.out.print&#40;&quot;Hello World!&quot;&#41;;
UiText.setText&#40;&quot;Score: &quot;+score&#41;;</pre></div></li><li
class="level1"><div
class="li"> Create one file named <code>Bundle.properties</code> in each directory where there are Java file that contain messages.</div></li><li
class="level1"><div
class="li"> For every hard-coded message, you add one line to the <code>Bundle.properties</code> file: First specify a unique key that identifies this string; then an equal sign; and the literal string itself. <br/><pre>greeting=Hello World!
score.display=Score: </pre></div></li><li
class="level1"><div
class="li"> In the source code, replace every occurence of a hard-coded message with the appropriate Resource Bundle call to its unique key:<pre>ResourceBundle.getBundle&#40;&quot;Bundle&quot;&#41;.getString&#40;&quot;greeting&quot;&#41;&#41;;
UiText.setText&#40;ResourceBundle.getBundle&#40;&quot;Bundle&quot;&#41;.getString&#40;&quot;score.display&quot;&#41;+score&#41;;</pre></div></li></ol><p> The language used in the Bundle.properties files will be the default language for your game.</p></div><h2><a
name="translating_the_messages">Translating the Messages</a></h2><div
class="level2"><p> Each additional language comes in a set of files that is marked with a (usually) two-letter suffix. Common locales are de for German, en for English, fr for French, ja for Japanese, pt for Portuguese, etc.</p><p> To translate the messages to another language, for example, German:</p><ol><li
class="level1"><div
class="li"> Make a copy of the <code>Bundle.properties</code> files.</div></li><li
class="level1"><div
class="li"> Name the copy <code>Bundle_de.properties</code> for German. Note the added suffix _de.</div></li><li
class="level1"><div
class="li"> Translate all strings (text on the right side of the equal sign) in the <code>Bundle_de.properties</code> to German.<pre>greeting=Hallo Welt!
score.display=Spielstand: </pre><p> <strong>Important:</strong> Do not modify any of the keys (text to the left of the equal sign)!</p></div></li><li
class="level1"><div
class="li"> To test the German localization, start the application from the command line with <code>-Duser.language=de</code>. Note the parameter <code>de</code>.</div></li></ol><p> <strong>Tip:</strong> In the jMonkeyPlatform, you set this VM Option in the Project properties under Run. Here you can also save individual run configuraions for each language you want to test.</p><p> To get the full list of language suffixes use</p><pre>Locale.getISOLanguages&#40;&#41;&#41;&#41;;</pre></div><h2><a
name="which_strings_not_to_translate">Which Strings Not to Translate</a></h2><div
class="level2"><p> <strong>Important:</strong> In the Bundle.properties file, do not include any strings that are asset paths, node or geometry names, input mappings, or material layers.</p><ul><li
class="level1"><div
class="li"> Keep material layers:<pre>mat.setTexture&#40;&quot;ColorMap&quot;, tex&#41;;</pre></div></li><li
class="level1"><div
class="li"> Keep paths:<pre>teapot = assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;</pre></div></li><li
class="level1"><div
class="li"> Keep geometry and node names:<pre>Geometry thing=new Geometry&#40;&quot;A thing&quot;, mesh&#41;;
Node vehicle = new Node&#40;&quot;Vehicle&quot;&#41;;</pre></div></li><li
class="level1"><div
class="li"> Keep mappings:<pre>inputManager.addMapping&#40;&quot;Shoot&quot;, trigger&#41;;
inputManager.addListener&#40;actionListener, &quot;Shoot&quot;&#41;;</pre></div></li></ul><p> Only localize messages and UI text!</p></div><h2><a
name="common_localization_problems">Common Localization Problems</a></h2><div
class="level2"><p> Typical problems include:</p><ul><li
class="level1"><div
class="li"> Localized strings will be of vastly different lengths and will totally break your UI layout. ⇒ Test every localization</div></li><li
class="level1"><div
class="li"> Strings with variable text or numbers don&#039;t work the same in different languages. ⇒ Either work in grammatical cases/numbers/gender for each language, or find a work-around.</div></li><li
class="level1"><div
class="li"> The localizer only sees the strings, without any context. E.g. does &quot;Search History&quot; mean &quot;display the history of searches&quot;, or &quot;search through the history&quot;? ⇒ Use clear key labels and work closely with the localizers if they require extra info.</div></li><li
class="level1"><div
class="li"> Broken international characters ⇒ Make sure the files are saved with the right character encoding for the language.</div></li></ul></div><h2><a
name="more_documentation">More Documentation</a></h2><div
class="level2"><p> <a
href="http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/">http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/</a></p><p> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Localisation">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Localisation</a></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:localization?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Localizing jME 3 Games</a></h1>
<div>
</div>
<h2><a>Scope</a></h2>
<div>
<p>
Localizing an application can mean several things:
</p>
<ul>
<li><div> At minimum you translate all messages and dialogs in the user interface to your target languages.</div>
</li>
<li><div> You should also translate the &quot;read me&quot;, help, and other documentation.</div>
</li>
<li><div> Also translating web content related to the application makes sure international users find out about your localized game.</div>
</li>
<li><div> If you go the whole way of internationalization, you also &quot;translate&quot; metaphors in icons or symbols used. <br/>
E.g. For localizations to right-to-left languages, you must also adjust the whole flow of the UI (order of menus and buttons).</div>
</li>
</ul>
<p>
There are tools that assist you with localizing Java Swing GUIs. jME3 applications do not typically have a Swing <acronym title="Graphical User Interface">GUI</acronym>, so those tools are not of much help. Just stick to the normal Java rules about using Bundle Properties:
</p>
</div>
<h2><a>Preparing the Localization</a></h2>
<div>
<p>
<strong>Tip:</strong> The jMonkeyPlatform supports opening and editing Bundle.properties files. Also note the Tools &gt; Localization menu.
</p>
<p>
To prepare the application for localization, you have to first identify all hard-coded messages.
</p>
<ol>
<li><div> Find every line in your jME3 game where you hard-coded message strings, e.g. <br/>
<pre>System.out.print&#40;&quot;Hello World!&quot;&#41;;
UiText.setText&#40;&quot;Score: &quot;+score&#41;;</pre>
</div>
</li>
<li><div> Create one file named <code>Bundle.properties</code> in each directory where there are Java file that contain messages.</div>
</li>
<li><div> For every hard-coded message, you add one line to the <code>Bundle.properties</code> file: First specify a unique key that identifies this string; then an equal sign; and the literal string itself. <br/>
<pre>greeting=Hello World!
score.display=Score: </pre>
</div>
</li>
<li><div> In the source code, replace every occurence of a hard-coded message with the appropriate Resource Bundle call to its unique key: <pre>ResourceBundle.getBundle&#40;&quot;Bundle&quot;&#41;.getString&#40;&quot;greeting&quot;&#41;&#41;;
UiText.setText&#40;ResourceBundle.getBundle&#40;&quot;Bundle&quot;&#41;.getString&#40;&quot;score.display&quot;&#41;+score&#41;;</pre>
</div>
</li>
</ol>
<p>
The language used in the Bundle.properties files will be the default language for your game.
</p>
</div>
<h2><a>Translating the Messages</a></h2>
<div>
<p>
Each additional language comes in a set of files that is marked with a (usually) two-letter suffix. Common locales are de for German, en for English, fr for French, ja for Japanese, pt for Portuguese, etc.
</p>
<p>
To translate the messages to another language, for example, German:
</p>
<ol>
<li><div> Make a copy of the <code>Bundle.properties</code> files.</div>
</li>
<li><div> Name the copy <code>Bundle_de.properties</code> for German. Note the added suffix _de.</div>
</li>
<li><div> Translate all strings (text on the right side of the equal sign) in the <code>Bundle_de.properties</code> to German. <pre>greeting=Hallo Welt!
score.display=Spielstand: </pre>
<p>
<strong>Important:</strong> Do not modify any of the keys (text to the left of the equal sign)!
</p>
</div>
</li>
<li><div> To test the German localization, start the application from the command line with <code>-Duser.language=de</code>. Note the parameter <code>de</code>.</div>
</li>
</ol>
<p>
<strong>Tip:</strong> In the jMonkeyPlatform, you set this VM Option in the Project properties under Run. Here you can also save individual run configuraions for each language you want to test.
</p>
<p>
To get the full list of language suffixes use
</p>
<pre>Locale.getISOLanguages&#40;&#41;&#41;&#41;;</pre>
</div>
<h2><a>Which Strings Not to Translate</a></h2>
<div>
<p>
<strong>Important:</strong> In the Bundle.properties file, do not include any strings that are asset paths, node or geometry names, input mappings, or material layers.
</p>
<ul>
<li><div> Keep material layers: <pre>mat.setTexture&#40;&quot;ColorMap&quot;, tex&#41;;</pre>
</div>
</li>
<li><div> Keep paths: <pre>teapot = assetManager.loadModel&#40;&quot;Models/Teapot/Teapot.obj&quot;&#41;;</pre>
</div>
</li>
<li><div> Keep geometry and node names: <pre>Geometry thing=new Geometry&#40;&quot;A thing&quot;, mesh&#41;;
Node vehicle = new Node&#40;&quot;Vehicle&quot;&#41;;</pre>
</div>
</li>
<li><div> Keep mappings: <pre>inputManager.addMapping&#40;&quot;Shoot&quot;, trigger&#41;;
inputManager.addListener&#40;actionListener, &quot;Shoot&quot;&#41;;</pre>
</div>
</li>
</ul>
<p>
Only localize messages and UI text!
</p>
</div>
<h2><a>Common Localization Problems</a></h2>
<div>
<p>
Typical problems include:
</p>
<ul>
<li><div> Localized strings will be of vastly different lengths and will totally break your UI layout. ⇒ Test every localization</div>
</li>
<li><div> Strings with variable text or numbers don&#039;t work the same in different languages. ⇒ Either work in grammatical cases/numbers/gender for each language, or find a work-around.</div>
</li>
<li><div> The localizer only sees the strings, without any context. E.g. does &quot;Search History&quot; mean &quot;display the history of searches&quot;, or &quot;search through the history&quot;? ⇒ Use clear key labels and work closely with the localizers if they require extra info.</div>
</li>
<li><div> Broken international characters ⇒ Make sure the files are saved with the right character encoding for the language.</div>
</li>
</ul>
</div>
<h2><a>More Documentation</a></h2>
<div>
<p>
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/"><param name="text" value="<html><u>http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/</u></html>"><param name="textColor" value="blue"></object>
</p>
<p>
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Localisation"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Localisation</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:localization?do=export_xhtmlbody">view online version</a></em></p>

@ -1,33 +1,98 @@
<h1><a
name="logging_and_monitoring">Logging and Monitoring</a></h1><div
class="level1"></div><h2><a
name="development_phase_log_output">Development Phase Log Output</a></h2><div
class="level2"><p> Many developers just use System.out.println() to print diagnostic strings to the terminal. The problem with that is that before the release, you&#039;d have to go through all your code and make certain you removed all these println() calls. You do not want your users to see them and worry about ominous strings babbling about old development diagnostics.</p><p> Instead of println(), you use the standard Java logger from <code>java.util.logging</code>. It has many advantages for professional game development:</p><ul><li
class="level1"><div
class="li"> You &quot;tag&quot; each message with a log level: Severe error, informative warning, etc.</div></li><li
class="level1"><div
class="li"> You can switch off printing of all messages up to certain log level with just one line of code.</div><ul><li
class="level2"><div
class="li"> During development, you would set the log level to fine, because you want all warnings printed.</div></li><li
class="level2"><div
class="li"> For the release, you set the log level to only report severe errors, and no informative diagnostics.</div></li></ul></li><li
class="level1"><div
class="li"> The logger string is localizable, since it contains variables. You may want to localize all errors.</div></li></ul><p> So to print comments like a pro, you use the following logger syntax. The variables a, b, c, can be any printable Java object, e.g. <code>Vector3f a = cam.getLocation()</code>. They are numbered {0},{1},{2},etc for use in the string, in the order you put them in the Object array.</p><pre>private static final Logger logger = Logger.getLogger&#40;HelloWorld.class.getName&#40;&#41;&#41;;</pre><p> Replace HelloWorld by the name of the class where you are using this line.</p><pre>logger.log&#40;Level.WARNING, &quot;ok seriously wtf somebody check why {0} is {1} again?!&quot;,
new Object&#91;&#93;&#123;a , b&#125;&#41;;</pre><p> or</p><pre>logger.log&#40;Level.SEVERE, &quot;Game error: {0} must not be {1} after {2}! Please check your flux generator.&quot;,
new Object&#91;&#93;&#123;a , b , c&#125;&#41;;</pre><p> As you see in the example, you should phrase potentially &quot;customer facing&quot; errors in a neutral way and offer a reason and a solution. If you use WARNINGs as replacement for casual printlns, make sure you deactivate them for the release.</p><p> More details about <a
href="http://download.oracle.com/javase/6/docs/api/java/util/logging/Level.html">Java log levels</a> here.</p></div><h3><a
name="switching_the_logger_on_and_off">Switching the Logger on and off</a></h3><div
class="level3"><p> In the release version you will deactivate the logging output to the terminal.</p><p> To deactivate the default logger, you set the log level to only report severe messages:</p><pre>Logger.getLogger&#40;””&#41;.setLevel&#40;Level.SEVERE&#41;;</pre><p> To reactivate it:</p><pre>Logger.getLogger&#40;””&#41;.setLevel&#40;Level.FINE&#41;;</pre></div><h2><a
name="jmonkeyplatform_log_files">jMonkeyPlatform Log Files</a></h2><div
class="level2"><p> You find the jMonkeyPlatform log file in /dev/var/log/messages.log in the jMonkeyPlatform preferences folder. You can learn the location of the preferences folder in the “About” screen of the jMonkeyPlatform under the label <strong>Userdir</strong>.</p><ul><li
class="level1"><div
class="li"> Windows: C:\Documents and Settings\YOUR_NAME\.jmonkeyplatform\&quot;</div></li><li
class="level1"><div
class="li"> Linux: /home/YOUR_NAME/.jmonkeyplatform/&quot;</div></li><li
class="level1"><div
class="li"> Mac <acronym
title="Operating System">OS</acronym>: <code>/Users/YOUR_NAME/Library/Application Support/jmonkeyplatform/</code></div></li></ul></div><h2><a
name="read_graphic_card_capabilites">Read Graphic Card Capabilites</a></h2><div
class="level2"><p> You can read the graphic card&#039;s capabilities using the <code>com.jme3.renderer.Caps</code> class:</p><pre>Collection&lt;Caps&gt; caps = renderer.getCaps&#40;&#41;;
Logger.getLogger&#40;HelloWorld.class.getName&#40;&#41;&#41;.log&#40;Level.INFO, “Caps: &#123;0&#125;” + caps.toString&#40;&#41;&#41;; </pre><p> Replace HelloWorld by the name of the class where you are using this line.</p><p> The result looks like the following example:</p><pre>Caps: [FrameBuffer, FrameBufferMRT, FrameBufferMultisample, OpenGL20, ARBprogram, GLSL100, GLSL110, GLSL120, VertexTextureFetch, FloatTexture, TextureCompressionLATC]</pre><p> This would tell you that this user&#039;s graphic card only supports OpenGL 2.0 and cannot handle newer OpenGL features.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:logging?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Logging and Monitoring</a></h1>
<div>
</div>
<h2><a>Logging Like a Newb</a></h2>
<div>
<p>
Many developers just use System.out.println() to print diagnostic strings to the terminal. The problem with that is that before the release, you&#039;d have to go through all your code and make certain you removed all these println() calls. You do not want your users to see them and worry about ominous strings babbling about old development diagnostics.
</p>
</div>
<h2><a>Logging Like a Pro</a></h2>
<div>
<p>
Instead of println(), you use the standard Java logger from <code>java.util.logging</code>. It has many advantages for professional game development:
</p>
<ul>
<li><div> You &quot;tag&quot; each message with a log level: Severe error, informative warning, etc.</div>
</li>
<li><div> You can switch off printing of all messages up to certain log level with just one line of code.</div>
<ul>
<li><div> During development, you would set the log level to fine, because you want all warnings printed.</div>
</li>
<li><div> For the release, you set the log level to only report severe errors, and no informative diagnostics.</div>
</li>
</ul>
</li>
<li><div> The logger string is localizable, since it contains variables. You may want to localize all errors.</div>
</li>
</ul>
<p>
So to print comments like a pro, you use the following logger syntax. The variables a, b, c, can be any printable Java object, e.g. <code>Vector3f a = cam.getLocation()</code>. They are numbered {0},{1},{2},etc for use in the string, in the order you put them in the Object array.
</p>
<pre>private static final Logger logger = Logger.getLogger&#40;HelloWorld.class.getName&#40;&#41;&#41;;</pre>
<p>
Replace HelloWorld by the name of the class where you are using this line.
</p>
<pre>logger.log&#40;Level.WARNING, &quot;ok seriously wtf somebody check why {0} is {1} again?!&quot;,
new Object&#91;&#93;&#123;a , b&#125;&#41;;</pre>
<p>
or
</p>
<pre>logger.log&#40;Level.SEVERE, &quot;Game error: {0} must not be {1} after {2}! Please check your flux generator.&quot;,
new Object&#91;&#93;&#123;a , b , c&#125;&#41;;</pre>
<p>
As you see in the example, you should phrase potentially &quot;customer facing&quot; errors in a neutral way and offer a reason and a solution. If you use WARNINGs as replacement for casual printlns, make sure you deactivate them for the release.
</p>
<p>
More details about <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://download.oracle.com/javase/6/docs/api/java/util/logging/Level.html"><param name="text" value="<html><u>Java log levels</u></html>"><param name="textColor" value="blue"></object> here.
</p>
</div>
<h2><a>Switching the Logger on and off</a></h2>
<div>
<p>
In the release version you will deactivate the logging output to the terminal.
</p>
<p>
To deactivate the default logger for a release, you set the log level to only report severe messages:
</p>
<pre>Logger.getLogger&#40;””&#41;.setLevel&#40;Level.SEVERE&#41;;</pre>
<p>
During development, you can tune down the default logger, and set the log level to only report warnings:
</p>
<pre>Logger.getLogger&#40;””&#41;.setLevel&#40;Level.WARNING&#41;;</pre>
<p>
To reactivate full logging, e.g. for debugging and testing:
</p>
<pre>Logger.getLogger&#40;””&#41;.setLevel&#40;Level.FINE&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:logging?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,176 @@
<h1><a>Making the Camera Follow a 3rd-Person Character</a></h1>
<div>
<p>
When players steer a game character with 1st-person view, they directly steer the camera (<code>flyCam.setEnabled(true);</code>), and they never see the walking character itself. In a game with 3rd-person view, however, the players see the character walk, and you (the game developer) want to make the camera follow the character around when it walks.
</p>
<p>
There are two ways how the camera can do that:
</p>
<ul>
<li><div> Registering a chase camera to the player and the input manager.</div>
</li>
<li><div> Attaching the camera to the character using a camera node.</div>
</li>
</ul>
<p>
<strong>Important:</strong> Using third-person view requires you to deactivate the default flyCam (first-person view). This means that you have to configure your own navigation (<a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">key inputs and analogListener</a>) that make your player character walk. For moving a physical player character, use <code>player.setWalkDirection()</code>, for a non-pysical character you can use <code>player.move()</code>.
</p>
</div>
<h2><a>Code Samples</a></h2>
<div>
<p>
Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestChaseCamera.java"><param name="text" value="<html><u>TestChaseCamera.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestCameraNode.java"><param name="text" value="<html><u>TestCameraNode.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Camera Node</a></h2>
<div>
<p>
To make the camera follow a target node, add this camera node code to your init method (e.g. <code>simpleInitApp()</code>). The <code>target</code> spatial is typically the player node.
</p>
<pre>// Disable the default flyby cam
flyCam.setEnabled&#40;false&#41;;
//create the camera Node
camNode = new CameraNode&#40;&quot;Camera Node&quot;, cam&#41;;
//This mode means that camera copies the movements of the target:
camNode.setControlDir&#40;ControlDirection.SpatialToCamera&#41;;
//Move camNode, e.g. behind and above the target:
camNode.setLocalTranslation&#40;new Vector3f&#40;0, 5, -5&#41;&#41;;
//Rotate the camNode to look at the target:
camNode.lookAt&#40;target.getLocalTranslation&#40;&#41;, Vector3f.UNIT_Y&#41;;
//Attach the camNode to the target:
target.attachChild&#40;camNode&#41;;</pre>
<p>
<strong>Important:</strong> Where the example says <code>camNode.setLocalTranslation(new Vector3f(0, 5, -5));</code>, you have to supply your own start position for the camera. This depends on the size of your target (the player character) and its position in your particular scene. Optimally, you set this to a spot a bit behind and above the target.
</p>
<div><table>
<tr>
<th>Methods</th><th>Description</th>
</tr>
<tr>
<td>setControlDir(ControlDirection.SpatialToCamera)</td><td>User input steers the target spatial, and the camera follows the spatial.<br/>
The spatial&#039;s transformation is copied over the camera&#039;s transformation. <br/>
Example: Use with <a href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">CharacterControl</a>led spatial.</td>
</tr>
<tr>
<td>setControlDir(ControlDirection.CameraToSpatial)</td><td>User input steers the camera, and the target spatial follows the camera. <br/>
The camera&#039;s transformation is copied over the spatial&#039;s transformation.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [2445-2926] -->
<p>
<strong>Code sample:</strong>
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestCameraNode.java"><param name="text" value="<html><u>TestCameraNode.java</u></html>"><param name="textColor" value="blue"></object> – Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
</li>
</ul>
</div>
<h2><a>Chase Camera</a></h2>
<div>
<p>
To activate the chase camera, add the following code to your init method (e.g. <code>simpleInitApp()</code>). The <code>target</code> spatial is typically the player node. You will be able to rotate the target by dragging (keeping the left mouse button pressed and moving the mouse).
</p>
<pre>// Disable the default flyby cam
flyCam.setEnabled&#40;false&#41;;
// Enable a chase cam for this target (typically the player).
ChaseCamera chaseCam = new ChaseCamera&#40;cam, target, inputManager&#41;;
chaseCam.setSmoothMotion&#40;true&#41;;</pre>
<div><table>
<tr>
<th>Method</th><th>Description</th>
</tr>
<tr>
<td>setInvertVerticalAxis(true)</td><td>Invert the camera&#039;s vertical rotation Axis </td>
</tr>
<tr>
<td>setInvertHorizontalAxis(true)</td><td>Invert the camera&#039;s horizontal rotation Axis</td>
</tr>
<tr>
<td>setTrailingEnabled(true)</td><td>Camera follows the target and flies around and behind when the target moves towards the camera. Trailing only works with smooth motion enabled. (Default)</td>
</tr>
<tr>
<td>setTrailingEnabled(false)</td><td>Camera follows the target, but does not rotate around the target when the target changes direction.</td>
</tr>
<tr>
<td>setSmoothMotion(true)</td><td>Activate SmoothMotion when trailing. This means the camera seems to accelerate and fly after the character, when it has caught up, it slows down again.</td>
</tr>
<tr>
<td>setSmoothMotion(false)</td><td>Disable smooth camera motion. Disabling SmoothMotion also disables trailing.</td>
</tr>
<tr>
<td>setLookAtOffset(Vector3f.UNIT_Y.mult(3))</td><td>Camera looks at a point 3 world units above the target.</td>
</tr>
<tr>
<td>setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE))</td><td>Enable rotation by keeping the middle mouse button pressed (like in Blender). This disables the rotation on right and left mouse button click.</td>
</tr>
<tr>
<td>setToggleRotationTrigger(new MouseButtonTrigger(<br/>
MouseInput.BUTTON_MIDDLE),<br/>
new KeyTrigger(KeyInput.KEY_SPACE))</td><td>Activate mutiple triggers for the rotation of the camera, e.g. spacebar and middle mouse button, etc.</td>
</tr>
<tr>
<td>setRotationSensitivity(5f)</td><td>How fast the camera rotates. Use values around &lt;1.0f (all bigger values are ignored).</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [3702-5114] -->
<p>
<strong>Code sample:</strong>
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/input/TestChaseCamera.java"><param name="text" value="<html><u>TestChaseCamera.java</u></html>"><param name="textColor" value="blue"></object> – Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.</div>
</li>
</ul>
</div>
<h2><a>Which to Choose?</a></h2>
<div>
<p>
What is the difference of the two code samples above?
</p>
<div><table>
<tr>
<th>CameraNode</th><th>ChaseCam</th>
</tr>
<tr>
<td>Camera follows immediately, flies at same speed as target.</td><td>Camera moves smoothly and accelerates and decelerates, flies more slowly than the target and catches up.</td>
</tr>
<tr>
<td>Camera stays attached to the target at a constant distance.</td><td>Camera orbits the target and approaches slowly.</td>
</tr>
<tr>
<td>Drag-to-Rotate rotates the target and the camera. You always see the target from behind.</td><td>Drag-to-Rotate rotates only the camera. You can see the target from various sides.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [5443-5914] -->
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:making_the_camera_follow_a_character?do=export_xhtmlbody">view online version</a></em></p>

@ -1,56 +1,113 @@
<h1><a
name="how_to_use_material_definitions_j3md">How to Use Material Definitions (.j3md)</a></h1><div
class="level1"><p> Typically, you create a set of custom materials, and use them throughout the game. For example, you can initialize and configure your materials objects in the <code>initSimpleApp()</code> method, and then load 3D models (Geometries) and use setMaterial() on them.</p><p> <strong>Tip:</strong> If you use one custom material very often, additionally read about storing material configurations in user-friendly <a
href="/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html">j3m Material Files</a>.</p></div><h2><a
name="preparing_a_material">Preparing a Material</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Choose a Material Definition from the <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> list that has the features that you need.</div><ul><li
class="level2"><div
class="li"> Tip: If you don&#039;t know, you can always start with <code>Unshaded.j3md</code>.</div></li></ul></li><li
class="level1"><div
class="li"> Look at the applicable parameters of the Material Definition and determine which ones you need to achieve the desired effect. Most parameters are optional.</div><ol><li
class="level2"><div
class="li"> Create and save the necessary Texture files to the assets directory.</div><ul><li
class="level3"><div
class="li"> E.g. ColorMap; DiffuseMap, NormalMap, AlphaMap, etc…</div></li></ul></li><li
class="level2"><div
class="li"> Determine the required values to achieve the effect that you want.</div><ul><li
class="level3"><div
class="li"> E.g. Colors, floats, booleans, etc…</div></li></ul></li></ol></li></ol></div><h2><a
name="using_a_material">Using a Material</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> In you Java code, create a Material object based on the .j3md file: e.g.<pre>Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;</pre></div></li><li
class="level1"><div
class="li"> Configure your Material by setting the appropriate values listed in the <a
href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> table. Here are examples of the methods that set the different data types:</div><ul><li
class="level2"><div
class="li"> <code>mat.setColor( &quot;Color&quot;, ColorRGBA.White );</code></div></li><li
class="level2"><div
class="li"> <code>mat.setTexture( &quot;ColorMap&quot;, assetManager.loadTexture(&quot;Interface/Logo/Monkey.png&quot; ));</code></div></li><li
class="level2"><div
class="li"> <code>mat.setFloat( &quot;Shininess&quot;, 5f);</code></div></li><li
class="level2"><div
class="li"> <code>mat.setBoolean( &quot;SphereMap&quot;, true);</code></div></li><li
class="level2"><div
class="li"> <code>mat.setVector3( &quot;NormalScale&quot;, new Vector3f(1f,1f,1f));</code></div></li></ul></li><li
class="level1"><div
class="li"> Use your prepared material on a Geometry:<pre>myGeometry.setMaterial&#40;mat&#41;;</pre></div></li><li
class="level1"><div
class="li"> (Optional) Adjust the texture scale:<pre>geometry.scaleTextureCoordinates&#40;new Vector2f&#40;1f, .5f&#41;&#41;;</pre></div></li></ol></div><h2><a
name="examples">Examples</a></h2><div
class="level2"><p> A simpled textured material.</p><pre>Material mat = new Material&#40;assetManager,
<h1><a>How to Use Material Definitions (.j3md)</a></h1>
<div>
<p>
Typically, you create a set of custom materials, and use them throughout the game. For example, you can initialize and configure your materials objects in the <code>initSimpleApp()</code> method, and then load 3D models (Geometries) and use setMaterial() on them.
</p>
<p>
<strong>Tip:</strong> If you use one custom material very often, additionally read about storing material configurations in user-friendly <a href="/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html">j3m Material Files</a>.
</p>
</div>
<h2><a>Preparing a Material</a></h2>
<div>
<ol>
<li><div> Choose a Material Definition from the <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> list that has the features that you need. </div>
<ul>
<li><div> Tip: If you don&#039;t know, you can always start with <code>Unshaded.j3md</code>.</div>
</li>
</ul>
</li>
<li><div> Look at the applicable parameters of the Material Definition and determine which ones you need to achieve the desired effect. Most parameters are optional.</div>
<ol>
<li><div> Create and save the necessary Texture files to the assets directory.</div>
<ul>
<li><div> E.g. ColorMap; DiffuseMap, NormalMap, AlphaMap, etc…</div>
</li>
</ul>
</li>
<li><div> Determine the required values to achieve the effect that you want.</div>
<ul>
<li><div> E.g. Colors, floats, booleans, etc… </div>
</li>
</ul>
</li>
</ol>
</li>
</ol>
</div>
<h2><a>Using a Material</a></h2>
<div>
<ol>
<li><div> In you Java code, create a Material object based on the .j3md file: e.g. <pre>Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;</pre>
</div>
</li>
<li><div> Configure your Material by setting the appropriate values listed in the <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> table. Here are examples of the methods that set the different data types:</div>
<ul>
<li><div> <code>mat.setColor( &quot;Color&quot;, ColorRGBA.White );</code></div>
</li>
<li><div> <code>mat.setTexture( &quot;ColorMap&quot;, assetManager.loadTexture(&quot;Interface/Logo/Monkey.png&quot; ));</code></div>
</li>
<li><div> <code>mat.setFloat( &quot;Shininess&quot;, 5f);</code></div>
</li>
<li><div> <code>mat.setBoolean( &quot;SphereMap&quot;, true);</code></div>
</li>
<li><div> <code>mat.setVector3( &quot;NormalScale&quot;, new Vector3f(1f,1f,1f));</code></div>
</li>
</ul>
</li>
<li><div> Use your prepared material on a Geometry: <pre>myGeometry.setMaterial&#40;mat&#41;;</pre>
</div>
</li>
<li><div> (Optional) Adjust the texture scale: <pre>geometry.scaleTextureCoordinates&#40;new Vector2f&#40;1f, .5f&#41;&#41;;</pre>
</div>
</li>
</ol>
</div>
<h2><a>Examples</a></h2>
<div>
<p>
A simpled textured material.
</p>
<pre>Material mat = new Material&#40;assetManager,
&quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.setTexture&#40;&quot;ColorMap&quot;, assetManager.loadTexture&#40;
&quot;Interface/Logo/Monkey.jpg&quot;&#41;&#41;;</pre><p> A textured material with a color bleeding through transparent areas.</p><pre>Material mat = new Material&#40;assetManager,
&quot;Interface/Logo/Monkey.jpg&quot;&#41;&#41;;</pre>
<p>
A textured material with a color bleeding through transparent areas.
</p>
<pre>Material mat = new Material&#40;assetManager,
&quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.setTexture&#40;&quot;ColorMap&quot;, assetManager.loadTexture&#40;
&quot;Textures/ColoredTex/Monkey.png&quot;&#41;&#41;;
mat.setColor&#40;&quot;Color&quot;, ColorRGBA.Blue&#41;;</pre><p> You can test these examples within the following code snippet. It creates a box and applies the material:</p><pre> Box&#40;Vector3f.ZERO, 1, 1, 1&#41;;
mat.setColor&#40;&quot;Color&quot;, ColorRGBA.Blue&#41;;</pre>
<p>
You can test these examples within the following code snippet. It creates a box and applies the material:
</p>
<pre> Box&#40;Vector3f.ZERO, 1, 1, 1&#41;;
Geometry geom = new Geometry&#40;&quot;Box&quot;, b&#41;;
// ... insert Material definition...
geom.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;geom&#41;;</pre><p> <strong>Tip:</strong> You can find these and other common code snippets in the jMonkeyPlatform Code Palette. Drag and drop them into your source code.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:material_definitions?do=export_xhtmlbody">view online version</a></em></p>
rootNode.attachChild&#40;geom&#41;;</pre>
<p>
<strong>Tip:</strong> You can find these and other common code snippets in the jMonkeyPlatform Code Palette. Drag and drop them into your source code.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:material_definitions?do=export_xhtmlbody">view online version</a></em></p>

@ -1,146 +1,279 @@
<h1><a
name="materials_overview">Materials Overview</a></h1><div
class="level1"><p> This table shows you which material definitions jME supplies by default, and how to make the most of your designer&#039;s 3D models by using material parameters.
If you are looking for information about how to use these materials in code, look at <a
href="/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html">Material Definitions</a> and <a
href="/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html">j3M Material Files</a>. <br/> <strong>Tip:</strong> The two most commonly used materials are Lighting.j3md and Unshaded.j3md (standard materials with and without Phong illumination, respectively).</p></div><h2><a
name="table_of_material_definitions">Table of Material Definitions</a></h2><div
class="level2"><p> Some parameters are &quot;optional&quot; because they are somewhat advanced. If you don&#039;t know what an option means, chances are that you are not using this feature in your textures – and you don&#039;t need to specify it. (E.g. YCoCg and LATC are image compression formats; Minnaert and WardIso are shader types.)
Also note that many other parameters are optional, even if they are not explicitly marked optional. For example, it&#039;s okay to specify solely the <code>DiffuseMap</code> and <code>NormalMap</code> when using <code>Lighting.j3md</code>. You are only using a subset of what is possible, but if that&#039;s what you want, you can do that. The developer should be in contact with the designer regarding what jME features individual Materials/Textures require.</p></div><h3><a
name="coloring_and_standard_textures">Coloring and Standard Textures</a></h3><div
class="level3"><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Material Definition</th><th
class="col1"> Usage</th><th
class="col2 leftalign"> Parameter : Type</th></tr><tr
class="row1"><td
class="col0"> Common/MatDefs/Misc/Unshaded.j3md</td><td
class="col1"> Standard unlit Material. Use this for simple coloring, simple texturing, simple glow, simple transparency. <br/> See also: <a
href="/com/jme3/gde/core/docs/jme3/beginner/hello_material.html">Hello Material</a></td><td
class="col2"> ColorMap : Texture <br/> LightMap : Texture <br/> Color : Color <br/> VertexColor : Boolean <br/> SeparateTexCoord : Boolean <br/> GlowMap : Texture <br/> GlowColor: Color</td></tr><tr
class="row2"><td
class="col0 leftalign"> Common/MatDefs/Misc/Sky.j3md</td><td
class="col1"> A solid skyblue, or use with a custom SkyDome texture. <br/> See also: <a
href="/com/jme3/gde/core/docs/jme3/advanced/sky.html">Sky</a></td><td
class="col2"> Texture : TextureCubeMap <br/> SphereMap : Boolean <br/> NormalScale : Vector3</td></tr><tr
class="row3"><td
class="col0"> Common/MatDefs/Terrain/Terrain.j3md</td><td
class="col1"> Splat textures for e.g. terrains. <br/> See also: <a
href="/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html">Hello Terrain</a></td><td
class="col2"> Texture1 : Texture (red) <br/> Texture1Scale : Float <br/> Texture2 : Texture (green) <br/> Texture2Scale : Float <br/> Texture3 : Texture (blue) <br/> Texture3Scale : Float <br/> Alpha : Texture</td></tr><tr
class="row4"><td
class="col0 leftalign"> Common/MatDefs/Misc/Particle.j3md</td><td
class="col1"> Used with texture masks for particle effects, or for point sprites. <br/> The Quadratic value scales the particle for perspective view (<a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/effect/ParticleEmitter.java">formula</a>). <br/> Does support an optional colored glow effect. <br/> See also: <a
href="/com/jme3/gde/core/docs/jme3/beginner/hello_effects.html">Hello Effects</a></td><td
class="col2"> Texture : Texture <br/> GlowMap : Texture <br/> GlowColor : Color <br/> Quadratic : Float <br/> PointSprite : Boolean</td></tr></table></div><p> <br/></p></div><h3><a
name="light_and_shadow">Light and Shadow</a></h3><div
class="level3"><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Material Definition</th><th
class="col1"> Usage</th><th
class="col2 leftalign"> Parameters</th></tr><tr
class="row1"><td
class="col0 leftalign"> Common/MatDefs/Light/Lighting.j3md</td><td
class="col1"> Standard lit material with Phong Illumination. Use this material together with DiffuseMap, SpecularMap, BumpMap (NormalMaps, ParalaxMap) textures. Supports shininess, transparency, and plain material colors (Diffuse, Ambient, Specular colors). <br/> See also: <a
href="/com/jme3/gde/core/docs/jme3/beginner/hello_material.html">Hello Material</a> <br/> <strong>Note:</strong> Lit materials require a <a
href="/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html">light source</a>! Glowing materials require a <a
href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">FilterPostProcessor</a>!</td><td
class="col2"> DiffuseMap : Texture <br/> UseAlpha<sup><a
href="#fn__1">1)</a></sup> : Boolean <br/> NormalMap : Texture <br/> LATC<sup><a
href="#fn__2">2)</a></sup> : Boolean <br/> SpecularMap : Texture <br/> Shininess : Float <br/> ParallaxMap : Texture <br/> AlphaMap : Texture <br/> AlphaDiscardThreshold: Float <br/> ColorRamp : Texture <br/> <strong>Glow (optional)</strong> <br/> GlowMap : Texture <br/> GlowColor : Color <br/> <strong>Performance and quality (optional)</strong> <br/> VertexLighting : Boolean <br/> UseVertexColor : Boolean <br/> LowQuality : Boolean <br/> HighQuality : Boolean <br/> <strong>Material Colors (optional)</strong> <br/> UseMaterialColors : Boolean <br/> Diffuse : Color <br/> Ambient : Color <br/> Specular : Color <br/> <strong>Tangent shading (optional):</strong> <br/> VTangent : Boolean <br/> Minnaert<sup><a
href="#fn__3">3)</a></sup> : Boolean <br/> WardIso<sup><a
href="#fn__4">4)</a></sup> : Boolean</td></tr><tr
class="row2"><td
class="col0">Common/MatDefs/Terrain/TerrainLighting.j3md</td><td
class="col1">Same kind of splat texture as Terrain.j3md, but with shading. <br/> Requires a light source.</td><td
class="col2">Color Diffuse : Color <br/> Ambient : Color <br/> Shininess : Float <br/> Specular : Color <br/> SpecularMap : Texture <br/> WardIso : Boolean <br/> useTriPlanarMapping : Boolean <br/> <strong>Texture Splat Maps</strong> <br/> DiffuseMap : Texture <br/> DiffuseMap_0_scale : Float <br/> NormalMap : Texture <br/> DiffuseMap_1 : Texture <br/> DiffuseMap_1_scale : Float <br/> NormalMap_1 : Texture <br/> DiffuseMap_2 : Texture <br/> DiffuseMap_2_scale : Float <br/> NormalMap_2 : Texture <br/> DiffuseMap_3 : Texture <br/> DiffuseMap_3_scale : Float <br/> NormalMap_3 : Texture <br/> <strong>Alpha Maps</strong> <br/> AlphaMap : Texture <br/> AlphaMap_1 : Texture <br/> AlphaMap_2 : Texture <br/> <strong>Glowing</strong> <br/> GlowMap : Texture <br/> GlowColor : Color</td></tr><tr
class="row3"><td
class="col0 leftalign"> Common/MatDefs/Light/Reflection.j3md</td><td
class="col1"> Reflective glass material with environment map (CubeMap/SphereMap). <br/> Requires light source. <br/> See also: <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/TestCubeMap.java">TestCubeMap.java</a></td><td
class="col2"> Texture : Texture <br/> SphereMap: Boolean</td></tr></table></div></div><h3><a
name="testing_and_debugging">Testing and Debugging</a></h3><div
class="level3"><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Material Definition</th><th
class="col1"> Usage</th><th
class="col2 leftalign"> Parameters</th></tr><tr
class="row1"><td
class="col0 leftalign"> Common/MatDefs/Misc/ShowNormals.j3md</td><td
class="col1"> A color gradient calculated from the model&#039;s surface normals. You can use this built-in material to test models that have no material, or as fall-back default material.</td><td
class="col2"> –</td></tr></table></div><p> <br/> <strong>Note:</strong> Common/MatDefs/Misc/SimpleTextured.j3md, ColoredTextured.j3md, VertexColor.j3md, Wireframe.j3md have been deprecated. Use equivalent features of Unshaded.j3md instead.</p></div><h2><a
name="transparency">Transparency</a></h2><div
class="level2"><p> Most Material Definitions support an alpha channel for transparency. In an RGBA color, the last float is the alpha channel: 0.0f is transparent, 1.0f is opaque. <br/> For example: <code>mat.setColor(&quot;Color&quot;, new ColorRGBA(1,0,0,0.5f));</code> is a half-opaque red. <br/> Additionally, you must specify a blendmode:</p><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0">Option</th><th
class="col1">Usage</th></tr><tr
class="row1"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.Off);</td><td
class="col1">Opaque</td></tr><tr
class="row2"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);</td><td
class="col1">Use this for normal transparency. Interpolates the background pixel with the current by using the current pixel&#039;s alpha. E.g. alpha-blended vegetation.</td></tr><tr
class="row3"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.Additive);</td><td
class="col1">Additive alpha blending adds colors in a commutative way, i.e. the result does not depend on the order of transparent layers. Adds the background pixel color with the current pixel color. E.g. particle effects that have black color as background.</td></tr><tr
class="row4"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);</td><td
class="col1">Same as &quot;Additive&quot;, except first it multiplies the current pixel color by the pixel alpha. E.g. used for particle effects that have alpha as background.</td></tr><tr
class="row5"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.Color);</td><td
class="col1">Blends by color. Generally useless.</td></tr><tr
class="row6"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.Modulate);</td><td
class="col1">Multiplies the background pixel by the current pixel.</td></tr><tr
class="row7"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);</td><td
class="col1">Same as &quot;Modulate&quot;, except the result is doubled.</td></tr><tr
class="row8"><td
class="col0">mat.getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);</td><td
class="col1">Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of &quot;Alpha&quot; blend mode.</td></tr><tr
class="row9"><td
class="col0">mat.getAdditionalRenderState().setDepthWrite(false);</td><td
class="col1">Use this if you have several transparent objects obscuring one another. Disables writing of the pixel&#039;s depth value to the depth buffer.</td></tr><tr
class="row10"><td
class="col0">mat.getAdditionalRenderState().setAlphaFallOff(0.5f); <br/> mat.getAdditionalRenderState().setAlphaTest(true)</td><td
class="col1">Enables alpha test, generally used for vegetation. Works the same way as &quot;AlphaDiscardThreshold&quot;.</td></tr></table></div><p> <br/> Also note the AlphaDiscardThreshold value for materials based on Lighting.j3md. The renderer does not render pixels whose transparancy is below the threshold.</p></div><h2><a
name="material_options">Material Options</a></h2><div
class="level2"><div
class="table sectionedit5"><table
class="inline"><tr
class="row0"><td
class="col0">mat.getAdditionalRenderState().setWireframe(true);</td><td
class="col1">Switch to showing the (textured) Material in wireframe mode</td></tr><tr
class="row1"><td
class="col0">mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); <br/> mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front); <br/> mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back); <br/> mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.FrontAndBack)</td><td
class="col1">Activate back- or frontface culling, both (=invisible), or off. Backface culling is activated by default as an optimization.</td></tr><tr
class="row2"><td
class="col0">mat.getAdditionalRenderState().setColorWrite(false);</td><td
class="col1">Disable writing the color of pixels. Use this together with setDepthWrite(true) to write pixels only to the depth buffer for example.</td></tr><tr
class="row3"><td
class="col0">mat.getAdditionalRenderState().setPointSprite(true);</td><td
class="col1">Enables point-sprite mode, so meshes with &quot;Mode.Points&quot; will be rendered as textured sprites. Note that gl_PointCoord must be set in the shader. Point sprites are used for hardware accelerated particle effects.</td></tr><tr
class="row4"><td
class="col0">mat.getAdditionalRenderState().setPolyOffset();</td><td
class="col1">Enable polygon offset. Use this when you have meshes that have triangles really close to each over (e.g. <a
href="http://en.wikipedia.org/wiki/Coplanarity">Coplanar</a>), it will shift the depth values to prevent <a
href="http://en.wikipedia.org/wiki/Z-fighting">Z-fighting</a>.</td></tr></table></div></div><div
class="footnotes"><div
class="fn"><sup><a
href="#fnt__1">1)</a></sup> UseAlpha specifies whether DiffuseMap uses the alpha channel</div><div
class="fn"><sup><a
href="#fnt__2">2)</a></sup> LATC Specifies whether NormalMap is BC5/ATI2n/LATC/3Dc-compressed</div><div
class="fn"><sup><a
href="#fnt__3">3)</a></sup> Minnaert is a shader type.</div><div
class="fn"><sup><a
href="#fnt__4">4)</a></sup> WardIso is a shader type.</div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:materials_overview?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Materials Overview</a></h1>
<div>
<p>
This table shows you which material definitions jME supplies by default, and how to make the most of your designer&#039;s 3D models by using material parameters.
If you are looking for information about how to use these materials in code, look at <a href="/com/jme3/gde/core/docs/jme3/advanced/material_definitions.html">Material Definitions</a> and <a href="/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html">j3M Material Files</a>.
</p>
<p>
<strong>Tip:</strong> Looks complicated? Remember two things: The most commonly used material is Lighting.j3md (which supports Phong illumination). The <a href="/com/jme3/gde/core/docs/sdk.html">jMonkeyPlatform</a> can create Material files, and it offers a visual editor where you can select and set properties, and preview the outcome. The Palatte contains code snippets that demo how to load materials.
</p>
</div>
<h2><a>Table of Material Definitions</a></h2>
<div>
<p>
Some parameters are &quot;optional&quot; because they are somewhat advanced. If you don&#039;t know what an option means, chances are that you are not using this feature in your textures – and you don&#039;t need to specify it. (E.g. YCoCg and LATC are image compression formats; Minnaert and WardIso are shader types.)
</p>
<p>
Also note that many other parameters are optional, even if they are not explicitly marked optional. For example, it&#039;s okay to specify solely the <code>DiffuseMap</code> and <code>NormalMap</code> when using <code>Lighting.j3md</code>. You are only using a subset of what is possible, but if that&#039;s what you want, you can do that. The developer should be in contact with the designer regarding what jME features individual Materials/Textures require.
</p>
</div>
<h3><a>Coloring and Standard Textures</a></h3>
<div>
<div><table>
<tr>
<th> Material Definition </th><th> Usage </th><th> Parameter : Type </th>
</tr>
<tr>
<td> Common/MatDefs/Misc/Unshaded.j3md </td><td> Standard unlit Material. Use this for simple coloring, simple texturing, simple glow, simple transparency. <br/>
See also: <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_material.html">Hello Material</a> </td><td> ColorMap : Texture <br/>
LightMap : Texture <br/>
Color : Color <br/>
VertexColor : Boolean <br/>
SeparateTexCoord : Boolean <br/>
GlowMap : Texture <br/>
GlowColor: Color </td>
</tr>
<tr>
<td> Common/MatDefs/Misc/Sky.j3md </td><td> A solid skyblue, or use with a custom SkyDome texture. <br/>
See also: <a href="/com/jme3/gde/core/docs/jme3/advanced/sky.html">Sky</a> </td><td> Texture : TextureCubeMap <br/>
SphereMap : Boolean <br/>
NormalScale : Vector3 </td>
</tr>
<tr>
<td> Common/MatDefs/Terrain/Terrain.j3md </td><td> Splat textures for e.g. terrains. <br/>
See also: <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html">Hello Terrain</a> </td><td> Texture1 : Texture (red) <br/>
Texture1Scale : Float <br/>
Texture2 : Texture (green) <br/>
Texture2Scale : Float <br/>
Texture3 : Texture (blue) <br/>
Texture3Scale : Float <br/>
Alpha : Texture </td>
</tr>
<tr>
<td> Common/MatDefs/Misc/Particle.j3md </td><td> Used with texture masks for particle effects, or for point sprites. <br/>
The Quadratic value scales the particle for perspective view (<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/effect/ParticleEmitter.java"><param name="text" value="<html><u>formula</u></html>"><param name="textColor" value="blue"></object>). <br/>
Does support an optional colored glow effect. <br/>
See also: <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_effects.html">Hello Effects</a> </td><td> Texture : Texture <br/>
GlowMap : Texture <br/>
GlowColor : Color <br/>
Quadratic : Float <br/>
PointSprite : Boolean </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1496-2939] -->
<p>
<br/>
</p>
</div>
<h3><a>Light and Shadow</a></h3>
<div>
<div><table>
<tr>
<th> Material Definition </th><th> Usage </th><th> Parameters </th>
</tr>
<tr>
<td> Common/MatDefs/Light/Lighting.j3md </td><td> Standard lit material with Phong Illumination. Use this material together with DiffuseMap, SpecularMap, BumpMap (NormalMaps, ParalaxMap) textures. Supports shininess, transparency, and plain material colors (Diffuse, Ambient, Specular colors). <br/>
See also: <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_material.html">Hello Material</a> <br/>
<strong>Note:</strong> Lit materials require a <a href="/com/jme3/gde/core/docs/jme3/advanced/light_and_shadow.html">light source</a>! Glowing materials require a <a href="/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html">FilterPostProcessor</a>! </td><td> DiffuseMap : Texture <br/>
UseAlpha<sup><a href="#fn__1">1)</a></sup> : Boolean <br/>
NormalMap : Texture <br/>
LATC<sup><a href="#fn__2">2)</a></sup> : Boolean <br/>
SpecularMap : Texture <br/>
Shininess : Float [1-128] <br/>
ParallaxMap : Texture <br/>
AlphaMap : Texture <br/>
AlphaDiscardThreshold: Float <br/>
ColorRamp : Texture <br/>
<strong>Glow (optional)</strong> <br/>
GlowMap : Texture <br/>
GlowColor : Color <br/>
<strong>Performance and quality (optional)</strong> <br/>
VertexLighting : Boolean <br/>
UseVertexColor : Boolean <br/>
LowQuality : Boolean <br/>
HighQuality : Boolean <br/>
<strong>Material Colors (optional)</strong> <br/>
UseMaterialColors : Boolean <br/>
Diffuse : Color <br/>
Ambient : Color <br/>
Specular : Color <br/>
<strong>Tangent shading (optional):</strong> <br/>
VTangent : Boolean <br/>
Minnaert<sup><a href="#fn__3">3)</a></sup> : Boolean <br/>
WardIso<sup><a href="#fn__4">4)</a></sup> : Boolean </td>
</tr>
<tr>
<td>Common/MatDefs/Terrain/TerrainLighting.j3md</td><td>Same kind of splat texture as Terrain.j3md, but with shading. <br/>
Requires a light source.</td><td>Color Diffuse : Color <br/>
Ambient : Color <br/>
Shininess : Float <br/>
Specular : Color <br/>
SpecularMap : Texture <br/>
WardIso : Boolean <br/>
useTriPlanarMapping : Boolean <br/>
<strong>Texture Splat Maps</strong> <br/>
DiffuseMap : Texture <br/>
DiffuseMap_0_scale : Float <br/>
NormalMap : Texture <br/>
DiffuseMap_1 : Texture <br/>
DiffuseMap_1_scale : Float <br/>
NormalMap_1 : Texture <br/>
DiffuseMap_2 : Texture <br/>
DiffuseMap_2_scale : Float <br/>
NormalMap_2 : Texture <br/>
DiffuseMap_3 : Texture <br/>
DiffuseMap_3_scale : Float <br/>
NormalMap_3 : Texture <br/>
<strong>Alpha Maps</strong> <br/>
AlphaMap : Texture <br/>
AlphaMap_1 : Texture <br/>
AlphaMap_2 : Texture <br/>
<strong>Glowing</strong> <br/>
GlowMap : Texture <br/>
GlowColor : Color </td>
</tr>
<tr>
<td> Common/MatDefs/Light/Reflection.j3md </td><td> Reflective glass material with environment map (CubeMap/SphereMap). <br/>
Requires light source. <br/>
See also: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/texture/TestCubeMap.java"><param name="text" value="<html><u>TestCubeMap.java</u></html>"><param name="textColor" value="blue"></object> </td><td> Texture : Texture <br/>
SphereMap: Boolean </td>
</tr>
</table></div>
<!-- EDIT2 TABLE [2970-5525] -->
<p>
<strong>Shininess Tip:</strong> To deactivate Shininess, do not set <code>Shininess</code> to 0, but instead set the <code>Specular</code> color to <code>ColorRGBA.Black</code>.
</p>
<p>
<strong>Bumpiness Tip:</strong> Before you can use NormalMaps, you must generate normals for the mesh (not the Geometry).
</p>
<pre>TangentBinormalGenerator.generate&#40;mesh&#41;;</pre>
</div>
<h3><a>Testing and Debugging</a></h3>
<div>
<div><table>
<tr>
<th> Material Definition </th><th> Usage </th><th> Parameters </th>
</tr>
<tr>
<td> Common/MatDefs/Misc/ShowNormals.j3md </td><td> A color gradient calculated from the model&#039;s surface normals. You can use this built-in material to test models that have no material, or as fall-back default material. </td><td></td>
</tr>
</table></div>
<!-- EDIT3 TABLE [5867-6152] -->
<p>
<br/>
<strong>Note:</strong> Common/MatDefs/Misc/SimpleTextured.j3md, ColoredTextured.j3md, VertexColor.j3md, Wireframe.j3md have been deprecated. Use equivalent features of Unshaded.j3md instead.
</p>
</div>
<h2><a>Transparency</a></h2>
<div>
<p>
Most Material Definitions support an alpha channel for transparency. In an RGBA color, the last float is the alpha channel: 0.0f is transparent, 1.0f is opaque. <br/>
For example: <code>mat.setColor(&quot;Color&quot;, new ColorRGBA(1,0,0,0.5f));</code> is a half-opaque red. <br/>
Additionally, you must specify a blendmode:
</p>
<div><table>
<tr>
<th>Option</th><th>Usage</th>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.Off);</td><td>Opaque</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);</td><td>Use this for normal transparency. Interpolates the background pixel with the current by using the current pixel&#039;s alpha. E.g. alpha-blended vegetation. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.Additive);</td><td>Additive alpha blending adds colors in a commutative way, i.e. the result does not depend on the order of transparent layers. Adds the background pixel color with the current pixel color. E.g. particle effects that have black color as background. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);</td><td>Same as &quot;Additive&quot;, except first it multiplies the current pixel color by the pixel alpha. E.g. used for particle effects that have alpha as background. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.Color);</td><td>Blends by color. Generally useless.</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.Modulate);</td><td>Multiplies the background pixel by the current pixel.</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);</td><td>Same as &quot;Modulate&quot;, except the result is doubled.</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);</td><td>Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of &quot;Alpha&quot; blend mode. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setDepthWrite(false);</td><td>Use this if you have several transparent objects obscuring one another. Disables writing of the pixel&#039;s depth value to the depth buffer. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setAlphaFallOff(0.5f); <br/>
mat.getAdditionalRenderState().setAlphaTest(true)</td><td>Enables alpha test, generally used for vegetation. Works the same way as &quot;AlphaDiscardThreshold&quot;.</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [6659-8462] -->
<p>
<br/>
Also note the AlphaDiscardThreshold value for materials based on Lighting.j3md. The renderer does not render pixels whose transparancy is below the threshold.
</p>
</div>
<h2><a>Material Options</a></h2>
<div>
<div><table>
<tr>
<td>mat.getAdditionalRenderState().setWireframe(true);</td><td>Switch to showing the (textured) Material in wireframe mode</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); <br/>
mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front); <br/>
mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back); <br/>
mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.FrontAndBack)</td><td>Activate back- or frontface culling, both (=invisible), or off. Backface culling is activated by default as an optimization.</td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setColorWrite(false);</td><td>Disable writing the color of pixels. Use this together with setDepthWrite(true) to write pixels only to the depth buffer for example. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setPointSprite(true);</td><td>Enables point-sprite mode, so meshes with &quot;Mode.Points&quot; will be rendered as textured sprites. Note that gl_PointCoord must be set in the shader. Point sprites are used for hardware accelerated particle effects. </td>
</tr>
<tr>
<td>mat.getAdditionalRenderState().setPolyOffset();</td><td>Enable polygon offset. Use this when you have meshes that have triangles really close to each over (e.g. <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/Coplanarity"><param name="text" value="<html><u>Coplanar</u></html>"><param name="textColor" value="blue"></object>), it will shift the depth values to prevent <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/Z-fighting"><param name="text" value="<html><u>Z-fighting</u></html>"><param name="textColor" value="blue"></object>.</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [8654-9943] -->
</div>
<div>
<div><sup><a href="#fnt__1">1)</a></sup>
UseAlpha specifies whether DiffuseMap uses the alpha channel</div>
<div><sup><a href="#fnt__2">2)</a></sup>
LATC Specifies whether NormalMap is BC5/ATI2n/LATC/3Dc-compressed</div>
<div><sup><a href="#fnt__3">3)</a></sup>
Minnaert is a shader type.</div>
<div><sup><a href="#fnt__4">4)</a></sup>
WardIso is a shader type.</div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:materials_overview?do=export_xhtmlbody">view online version</a></em></p>

@ -1,129 +1,163 @@
<h1><a
name="polygon_meshes">Polygon Meshes</a></h1><div
class="level1"><p> <a
href="/wiki/lib/exe/detail.php/jme3:dolphin-mesh.png?id=jme3%3Aadvanced%3Amesh"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/dolphin-mesh.png" class="mediaright" align="right" alt="" /></a></p><p> All visible game elements in a scene, whether it is a Model or a Shape, are made up of polygon meshes. JME3 has a com.jme3.scene.Mesh class that represents all meshes.</p><ul><li
class="level1"><div
class="li"> Meshes are made up of triangles. <br/> <code>getTriangleCount(…)</code> and <code>getTriangle(…)</code></div></li><li
class="level1"><div
class="li"> Each mesh has a unique ID <br/> <code>getId()</code></div></li><li
class="level1"><div
class="li"> Meshes have transformations: Location (local translation), rotation, scale.</div></li><li
class="level1"><div
class="li"> Meshes have a bounding volume. jME3 can detect intersections (that is, non-physical collisions) between meshes, or between meshes and 2D elements such as rays. <br/> <code>collideWith()</code>.</div></li><li
class="level1"><div
class="li"> Meshes are locked with <code>setStatic()</code> and unlocked with <code>setDynamic()</code>.</div><ul><li
class="level2"><div
class="li"> Static Meshes cannot be modified, but are more optimized and faster (they can be precalculated).</div></li><li
class="level2"><div
class="li"> Dynamic Meshes can be modified live, but are not optimized and slower.</div></li></ul></li><li
class="level1"><div
class="li"> (Optional) Meshes can have a LOD (level of detail optimization) that renders more or less details depending on distance from the camera.</div></li></ul><p> You can use default <a
href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s as meshes; load <a
href="/com/jme3/gde/core/docs/jme3/advanced/3d_models.html">3D models</a> (i.e. meshes created in external applications); or create free-form <a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html">custom meshes</a> programmatically.</p></div><h2><a
name="vertex_buffer">Vertex Buffer</a></h2><div
class="level2"><p> The VertexBuffer contains a particular type of geometry data used by Meshes. Every VertexBuffer set on a Mesh is sent as an attribute to the vertex shader to be processed.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0">Vertex Buffer Type</th><th
class="col1">Description</th></tr><tr
class="row1"><td
class="col0">Type.Position</td><td
class="col1">Position of the vertex (3 floats)</td></tr><tr
class="row2"><td
class="col0">Type.Index</td><td
class="col1"> Specifies the index buffer, must contain integer data.</td></tr><tr
class="row3"><td
class="col0">Type.TexCoord</td><td
class="col1"> Texture coordinate</td></tr><tr
class="row4"><td
class="col0">Type.TexCoord2</td><td
class="col1"> Texture coordinate #2</td></tr><tr
class="row5"><td
class="col0">Type.Normal</td><td
class="col1"> Normal vector, normalized.</td></tr><tr
class="row6"><td
class="col0">Type.Tangent</td><td
class="col1"> Tangent vector, normalized.</td></tr><tr
class="row7"><td
class="col0">Type.Binormal</td><td
class="col1"> Binormal vector, normalized.</td></tr><tr
class="row8"><td
class="col0">Type.Color</td><td
class="col1"> Color and Alpha (4 floats)</td></tr><tr
class="row9"><td
class="col0">Type.Size</td><td
class="col1">The size of the point when using point buffers.</td></tr><tr
class="row10"><td
class="col0">Type.InterleavedData</td><td
class="col1"> Specifies the source data for various vertex buffers when interleaving is used.</td></tr><tr
class="row11"><td
class="col0">Type.BindPosePosition</td><td
class="col1"> Inital vertex position, used with animation.</td></tr><tr
class="row12"><td
class="col0">Type.BindPoseNormal</td><td
class="col1"> Inital vertex normals, used with animation</td></tr><tr
class="row13"><td
class="col0">Type.BoneWeight</td><td
class="col1"> Bone weights, used with animation</td></tr><tr
class="row14"><td
class="col0">Type.BoneIndex</td><td
class="col1"> Bone indices, used with animation</td></tr></table></div><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">Mesh method</th><th
class="col1">Description</th></tr><tr
class="row1"><td
class="col0" colspan="2">setLineWidth(1)</td></tr><tr
class="row2"><td
class="col0" colspan="2">setPointSize(4.0f)</td></tr><tr
class="row3"><td
class="col0" colspan="2">setBound(boundingVolume)</td></tr><tr
class="row4"><td
class="col0">setStatic()</td><td
class="col1">Locks the mesh so you cannot modify it anymore, thus optimizing its data (faster).</td></tr><tr
class="row5"><td
class="col0">setDynamic()</td><td
class="col1">Unlocks the mesh so you can modified it, but this will un-optimize the data (slower).</td></tr><tr
class="row6"><td
class="col0">setMode(Mesh.Mode.Points)</td><td
class="col1"> Used to set mesh modes, see below</td></tr><tr
class="row7"><td
class="col0" colspan="2">getId()</td></tr><tr
class="row8"><td
class="col0" colspan="2">getTriangle(int,tri)</td></tr><tr
class="row9"><td
class="col0" colspan="2">scaleTextureCoordinates(Vector2f)</td></tr></table></div><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0">Mesh Mode</th><th
class="col1">Description</th></tr><tr
class="row1"><td
class="col0">Mesh.Mode.Points</td><td
class="col1">Show only corner points</td></tr><tr
class="row2"><td
class="col0">Mesh.Mode.Lines</td><td
class="col1">Show lines</td></tr><tr
class="row3"><td
class="col0">Mesh.Mode.LineLoop</td><td
class="col1">?</td></tr><tr
class="row4"><td
class="col0">Mesh.Mode.LineStrip</td><td
class="col1">?</td></tr><tr
class="row5"><td
class="col0">Mesh.Mode.Triangles</td><td
class="col1">?</td></tr><tr
class="row6"><td
class="col0">Mesh.Mode.TriangleStrip</td><td
class="col1">?</td></tr><tr
class="row7"><td
class="col0">Mesh.Mode.TriangleFan</td><td
class="col1">?</td></tr><tr
class="row8"><td
class="col0">Mesh.Mode.Hybrid</td><td
class="col1">?</td></tr></table></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:mesh?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Polygon Meshes</a></h1>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/dolphin-mesh.png">
</p>
<p>
All visible game elements in a scene, whether it is a Model or a Shape, are made up of polygon meshes. JME3 has a com.jme3.scene.Mesh class that represents all meshes.
</p>
<ul>
<li><div> Meshes are made up of triangles. <br/>
<code>getTriangleCount(…)</code> and <code>getTriangle(…)</code></div>
</li>
<li><div> Each mesh has a unique ID <br/>
<code>getId()</code></div>
</li>
<li><div> Meshes have transformations: Location (local translation), rotation, scale.</div>
</li>
<li><div> Meshes have a bounding volume. jME3 can detect intersections (that is, non-physical collisions) between meshes, or between meshes and 2D elements such as rays. <br/>
<code>collideWith()</code>.</div>
</li>
<li><div> Meshes are locked with <code>setStatic()</code> and unlocked with <code>setDynamic()</code>. </div>
<ul>
<li><div> Static Meshes cannot be modified, but are more optimized and faster (they can be precalculated). </div>
</li>
<li><div> Dynamic Meshes can be modified live, but are not optimized and slower. </div>
</li>
</ul>
</li>
<li><div> (Optional) Meshes can have a LOD (level of detail optimization) that renders more or less details depending on distance from the camera.</div>
</li>
</ul>
<p>
You can use default <a href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s as meshes; load <a href="/com/jme3/gde/core/docs/jme3/advanced/3d_models.html">3D models</a> (i.e. meshes created in external applications); or create free-form <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html">custom meshes</a> programmatically.
</p>
</div>
<h2><a>Vertex Buffer</a></h2>
<div>
<p>
The VertexBuffer contains a particular type of geometry data used by Meshes. Every VertexBuffer set on a Mesh is sent as an attribute to the vertex shader to be processed.
</p>
<div><table>
<tr>
<th>Vertex Buffer Type</th><th>Description</th>
</tr>
<tr>
<td>Type.Position </td><td>Position of the vertex (3 floats)</td>
</tr>
<tr>
<td>Type.Index </td><td> Specifies the index buffer, must contain integer data.</td>
</tr>
<tr>
<td>Type.TexCoord </td><td> Texture coordinate</td>
</tr>
<tr>
<td>Type.TexCoord2 </td><td> Texture coordinate #2</td>
</tr>
<tr>
<td>Type.Normal </td><td> Normal vector, normalized.</td>
</tr>
<tr>
<td>Type.Tangent </td><td> Tangent vector, normalized.</td>
</tr>
<tr>
<td>Type.Binormal </td><td> Binormal vector, normalized.</td>
</tr>
<tr>
<td>Type.Color </td><td> Color and Alpha (4 floats)</td>
</tr>
<tr>
<td>Type.Size </td><td>The size of the point when using point buffers.</td>
</tr>
<tr>
<td>Type.InterleavedData </td><td> Specifies the source data for various vertex buffers when interleaving is used.</td>
</tr>
<tr>
<td>Type.BindPosePosition </td><td> Inital vertex position, used with animation.</td>
</tr>
<tr>
<td>Type.BindPoseNormal </td><td> Inital vertex normals, used with animation</td>
</tr>
<tr>
<td>Type.BoneWeight </td><td> Bone weights, used with animation</td>
</tr>
<tr>
<td>Type.BoneIndex </td><td> Bone indices, used with animation</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1417-2236] --><div><table>
<tr>
<th>Mesh method</th><th>Description</th>
</tr>
<tr>
<td>setLineWidth(1)</td>
</tr>
<tr>
<td>setPointSize(4.0f)</td>
</tr>
<tr>
<td>setBound(boundingVolume)</td>
</tr>
<tr>
<td>setStatic()</td><td>Locks the mesh so you cannot modify it anymore, thus optimizing its data (faster).</td>
</tr>
<tr>
<td>setDynamic()</td><td>Unlocks the mesh so you can modified it, but this will un-optimize the data (slower).</td>
</tr>
<tr>
<td>setMode(Mesh.Mode.Points)</td><td> Used to set mesh modes, see below</td>
</tr>
<tr>
<td>getId()</td>
</tr>
<tr>
<td>getTriangle(int,tri)</td>
</tr>
<tr>
<td>scaleTextureCoordinates(Vector2f)</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [2238-2665] --><div><table>
<tr>
<th>Mesh Mode</th><th>Description</th>
</tr>
<tr>
<td>Mesh.Mode.Points</td><td>Show only corner points</td>
</tr>
<tr>
<td>Mesh.Mode.Lines</td><td>Show lines</td>
</tr>
<tr>
<td>Mesh.Mode.LineLoop</td><td>?</td>
</tr>
<tr>
<td>Mesh.Mode.LineStrip</td><td>?</td>
</tr>
<tr>
<td>Mesh.Mode.Triangles</td><td>?</td>
</tr>
<tr>
<td>Mesh.Mode.TriangleStrip</td><td>?</td>
</tr>
<tr>
<td>Mesh.Mode.TriangleFan</td><td>?</td>
</tr>
<tr>
<td>Mesh.Mode.Hybrid</td><td>?</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [2667-2908] -->
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:mesh?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,324 @@
<h1><a>Monkey Zone: Multi-player Sample Project</a></h1>
<div>
<p>
MonkeyZone is an multi-player demo game provided by the jME core developer team.
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://monkeyzone.googlecode.com/svn/trunk/"><param name="text" value="<html><u>Download source code</u></html>"><param name="textColor" value="blue"></object> (Subversion Repository)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.youtube.com/watch?v=98yITEoJvqE"><param name="text" value="<html><u>Watch pre-alpha video footage</u></html>"><param name="textColor" value="blue"></object> (YouTube Video)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2011/02/13/monkeyzone-a-jme3-game-from-the-core/"><param name="text" value="<html><u>Read &quot;MonkeyZone – a jME3 game from the core&quot;</u></html>"><param name="textColor" value="blue"></object> (news article)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/user-code-projects/forum/topic/open-game-finder/"><param name="text" value="<html><u>Related forum thread: Open Game Finder</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
This open-source demo:
</p>
<ol>
<li><div> showcases one possible way to implement a game with jME3, and</div>
</li>
<li><div> helps the jME team verify the jME3 <acronym title="Application Programming Interface">API</acronym> in terms of usability.</div>
</li>
</ol>
<p>
The game idea is based on “BattleZone” arcade game from the 1980s, a first-person shooter the with real-time strategy elements.
The game was written using the jMonkeyPlatform IDE, and it&#039;s based off the BasicGame project template. It took us one week to create a playable pre-alpha, including networking.
The project design follows best practices that make it possible to edit maps, vehicles, etc, in jMonkeyPlatform without having to change the code – This allows 3D graphic designers to contribute models more easily. (If you feel like contributing assets or working on parts of the game code, drop us a note!)
</p>
</div>
<h2><a>Implementation</a></h2>
<div>
<p>
MonkeyZone is a multi-player game with a physics simulation. Both, clients and server, run the physics simulation. The clients send input data from the player group to the server, where they control the entities, and also broadcast to the clients. Additionally, the server sends regular syncronization data for all objects in the game to prevent drifting.
When a human user or an AI performs an action (presses a button), the actual logic is done on the server. The results are broadcast as data messages to the entities. When the entity is controlled by an AI, the actual AI code (that determines where the entity should move, and when it should perform an action) is executed on the client.
<br/>
<br/>
<em>The way MonkeyZone is implemented is just one of the many possible ways to do a game like this in jME. Some things might be done more efficiently, some might be done in another way completely. MonkeyZone tries to do things the way that are most appropriate to implement the game at hand and it shows nicely how jME3 and the standard Java <acronym title="Application Programming Interface">API</acronym> can make game development easier and faster. Also note that the way MonkeyZone is designed is not scalable to a MMO style game, it will only work in a FPS style environment where the whole game world can be loaded at once.</em>
</p>
</div>
<h3><a>Terminology</a></h3>
<div>
<p>
The game uses certain terms that might be familiar to you but maybe used in another way, so heres a quick rundown on the terms being used.
</p>
<ul>
<li><div> Player – Logical human or AI player that can enter entities and generally act, only exists as PlayerData “database” with an id.</div>
</li>
<li><div> Entity – Spatial with UserData, a world object like character, vehicle, box or factory. The base form is defined only by a String pointing to the j3o which already has all userdata like hitpoints, speed etc.</div>
</li>
<li><div> User – Human player using a client</div>
</li>
<li><div> Player Group – Group of players that play together (e.g. one human player and one AI companion per client). For now that&#039;s the same as client_id of human player for all AIControl’ed players originating from that client.</div>
</li>
<li><div> Client – Computer connected to server</div>
</li>
</ul>
</div>
<h3><a>Manager Classes</a></h3>
<div>
<p>
The WorldManager does the main work of organizing players, entities and the world and synchronizing them between the server and client. Both client and server use this class. Some other managers like ClientEffectsManager only exist on the client or server and manage e.g. effects display.
The gameplay is largely controlled by the ServerGameManager which does gameplay logic on the server, combined with the actions issued by the AI and user on the client (see below) it implements the gameplay. It extensively uses the functions exposed by the WorldManager to perform actions and gather data. This is also the class where the actions of the players are actually executed on the server to determine the outcome (ray testing for shooting etc.).
</p>
</div>
<h3><a>Use of Controls</a></h3>
<div>
<p>
<a href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Controls</a> are used extensively in MonkeyZone for many aspects of the game. When a player enters an entity, the Spatials Controls are configured based on the player that enters. For example when the human user enters an entity, Controls that update the user interface (DefaultHUDControl) or user input (UserInputControl) are added to the current entity Spatial.
</p>
</div>
<h4><a>...As entity capabilities</a></h4>
<div>
<p>
Controls attached to Spatials are generally used like an “array of capabilities” that the entity posesses. So when an entity has a VehicleControl its expected to be a vehicle, when its got a CharacterControl its expected to be a character.
Other Controls work completely on their own, like CharacterAnimControl which just uses the CharacterControl of the entity to check if the character is running, jumping etc. and then animates the entity if it has an AnimControl.
</p>
</div>
<h4><a>... to abstract</a></h4>
<div>
<p>
Furthermore theres special interfaces for Controls that allow abstraction of different Controls into one base interface. For example ManualControl and AutonomousControl are interfaces for controls that manage the movement of a spatial in a generalized way. This way AI code and e.g. the UserInputControl only have to check for a valid AutonomousControl or ManualControl on the spatial to control and move it. The details of the movement are handled by classes like ManualVehicleControl and AutonomousCharacterControl.
</p>
</div>
<h4><a>... for AI functions</a></h4>
<div>
<p>
A special Control called CommandControl handles the Commands that can be executed by user controlled players, see below.
</p>
</div>
<h3><a>Artificial Intelligence</a></h3>
<div>
<p>
MonkeyZone includes simple AI functions based on a command queue.
</p>
</div>
<h4><a>Commands</a></h4>
<div>
<p>
To implement autonomous AI players MonkeyZone uses a system of Commands that are managed by a CommandControl that is attached to each AI player entity controlled by the user. This CommandControl manages a list of Commands that are executed based on priority. For example theres a MoveCommand, a FollowCommand and an AttackCommand, Commands can however implement more complete behavior than that, e.g. the complete logic for a scavenging entity.
</p>
<ul>
<li><div> Press the WASD keys and use the mouse to move</div>
</li>
<li><div> press space to jump</div>
</li>
<li><div> Aim and click to shoot</div>
</li>
<li><div> Type 1 to select the first Ogre</div>
<ul>
<li><div> Aim at the floor and press F1 to tell it where to go.</div>
</li>
<li><div> Aim at a target and press F2 to tell it who to follow.</div>
</li>
<li><div> Aim at a target and press F3 to tell it who to attack.</div>
</li>
<li><div> Aim at the car and press F4 to make it drive the car.</div>
</li>
<li><div> Walk close to the car and press enter to drive the car.</div>
</li>
</ul>
</li>
</ul>
</div>
<h4><a>Triggers</a></h4>
<div>
<p>
The SphereTrigger is a TriggerControl that is also attached to each AI players current entity. It consists of a GhostControl that checks the overlapping entities around the entity its attached to. It can be assigned a command that is checked with every entity entering the SphereTrigger and executed if applicable (e.g. normal “attack enemy” mode).
</p>
</div>
<h4><a>NavMesh</a></h4>
<div>
<p>
For each map a navigation mesh is generated that allows the entities to navigate the terrain. Autonomous entities automatically get a NavigationControl based on the current map. The AutonomousControl implementations automatically recognize the NavigationControl attached to the Spatial and use it for navigation. The NavMeshNavigationControl implementation contains a reference to the levels NavMesh and implements a navigation algorithm similar to the A* algorithm.
</p>
</div>
<h3><a>Networking</a></h3>
<div>
<p>
Networking is realized in the PhysicsSyncManager which we hope to extend to a state where it can serve as a general sync system for physics based network games.
The sync manager basically puts a timestamp on every message sent from the server and then buffers all arriving messages on the client within a certain time window. This allows to compensate for messages arriving too soon or too late within the constraints of the buffer, a future version might step the clients physics space different to compensate for network delays without “snapping”.
</p>
</div>
<h2><a>Use of jMonkeyPlatform tools</a></h2>
<div>
<p>
All assets used in the game, like entity models and loaded maps can be preconfigured and edited using jMonkeyPlatform. For example, to add a new vehicle type, a vehicle is created in the jMP vehicle editor and UserData like Speed, HitPoints etc. is applied directly in the editor. When the model is loaded in the game it is automatically configured based on these settings, the same accounts for maps that are loaded, special Nodes that mark e.g. player start locations are recognized automatically etc.
</p>
</div>
<h3><a>UserData</a></h3>
<div>
<p>
Entities that are loaded from disk have certain UserData like HitPoints, Speed etc. that is used to configure the entity at runtime. jMP allows adding and editing this UserData so entity properties are editable visually.
</p>
</div>
<h3><a>Physics</a></h3>
<div>
<p>
VehicleControls, CharacterControls and RigidBodyControls with mesh collision shape for terrain and objects are generated in jMP and saved in the entity j3o file. When an entity is loaded, the type of entity is identified based on the available controls and UserData and it is configured accordingly.
</p>
</div>
<h2><a>API Info</a></h2>
<div>
</div>
<h3><a>Designer Infos</a></h3>
<div>
<p>
Editable UserData of entity Spatials:
</p>
<ul>
<li><div> (float) HitPoints</div>
</li>
<li><div> (float) MaxHitPoints</div>
</li>
<li><div> (float) Speed</div>
</li>
</ul>
<p>
Entity Spatial marking Node names:
</p>
<ul>
<li><div> AimNode</div>
</li>
<li><div> CameraAttachment</div>
</li>
<li><div> ShootAttachment</div>
</li>
</ul>
<p>
Level Spatial marking Node names:
</p>
<ul>
<li><div> StartPoint</div>
</li>
<li><div> PowerSource</div>
</li>
<li><div> MetalField</div>
</li>
</ul>
</div>
<h4><a>Developer Infos</a></h4>
<div>
<p>
Programmatic UserData of entities:
</p>
<ul>
<li><div> (long) entity_id</div>
</li>
<li><div> (int) group_id</div>
</li>
<li><div> (long) player_id</div>
</li>
</ul>
<p>
Programmatic PlayerData:
</p>
<ul>
<li><div> (long) id</div>
</li>
<li><div> (int) group_id</div>
</li>
<li><div> (long) entity_id</div>
</li>
<li><div> (long) character_entity_id</div>
</li>
</ul>
</div>
<h2><a>The Future</a></h2>
<div>
<p>
Have a look at the code and feel free to ask about it, if you want any new features, you are free to implement them. ;)
MonkeyZone is hosted at GoogleCode, where you can check out the jMonkeyPlatform-ready project via svn:
</p>
<ol>
<li><div> jMonkeyPlatform→Team→Subversion→Checkout,</div>
</li>
<li><div> Enter the SVN <acronym title="Uniform Resource Locator">URL</acronym> <code><object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://monkeyzone.googlecode.com/svn/trunk/"><param name="text" value="<html><u>http://monkeyzone.googlecode.com/svn/trunk/</u></html>"><param name="textColor" value="blue"></object></code></div>
</li>
<li><div> Download, open, and build the project</div>
</li>
<li><div> Run the server first (com.jme3.monkeyzone.ServerMain), and then a client (com.jme3.monkeyzone.ClientMain).</div>
</li>
</ol>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:monkey_zone?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,120 @@
<h1><a>MotionPath</a></h1>
<div>
<p>
A MotionPath describes the motion of a spatial between waypoints. The path can be linear or rounded. You use MotionPaths to remote-control a spatial, or the camera.
</p>
<p>
<strong>Tip:</strong> If you want to remote-control a whole cutscene with several spatials moving at various times, then we recommened you use MotionPaths together with <a href="/com/jme3/gde/core/docs/jme3/advanced/cinematics.html">Cinematics</a>.
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestMotionPath.java"><param name="text" value="<html><u>TestMotionPath.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCameraMotionPath.java"><param name="text" value="<html><u>TestCameraMotionPath.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>What Are Way Points?</a></h2>
<div>
<p>
When shooting a movie scene, the director tells actors where to walk, for example, by drawing a series of small crosses on the floor. Cameramen often mount the camera on rails (so called dolly track) so they can follow along complex scenes more easily.
</p>
<p>
In JME3, you use MotionPaths to specify a series of positions for a character or the camera. The MotionPath automatically updates the transformation of the spatial in each frame to make it move from one point to the next.
</p>
<ul>
<li><div> <strong>A way point</strong> is one positions on a path. </div>
</li>
<li><div> <strong>A MotionPath</strong> contains a list of all way points of one path. </div>
</li>
</ul>
<p>
The final shape of the path is computed using a linear interpolation or a <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.mvps.org/directx/articles/catmull/"><param name="text" value="<html><u>Catmull-Rom</u></html>"><param name="textColor" value="blue"></object> spline interpolation on the way points.
</p>
</div>
<h2><a>Create a MotionPath</a></h2>
<div>
<p>
Create a Motionpath object and add way points to it.
</p>
<pre>MotionPath path = new MotionPath&#40;&#41;;
path.addWayPoint&#40;new Vector3f&#40;10, 3, 0&#41;&#41;;
path.addWayPoint&#40;new Vector3f&#40;8, -2, 1&#41;&#41;;
...</pre>
<p>
You can configure the path as follows.
</p>
<div><table>
<tr>
<th> MotionPath Method </th><th> Usage </th>
</tr>
<tr>
<td>path.setCycle(true)</td><td>Sets whether the motion along this path should be closed (true) or open-ended (false). </td>
</tr>
<tr>
<td>path.addWayPoint(vector)</td><td>Adds individual waypoints to this path. The order is relevant.</td>
</tr>
<tr>
<td>path.removeWayPoint(vector) <br/>
removeWayPoint(index)</td><td>Removes a way point from this path. You can specify the point that you want to remove as vector or as integer index.</td>
</tr>
<tr>
<td>path.setCurveTension(0.83f)</td><td>Sets the tension of the curve (Catmull-Rom Spline). A value of 0.0f results in a straight linear line, 1.0 a very round curve.</td>
</tr>
<tr>
<td>path.getNbWayPoints()</td><td>Returns the number of waypoints in this path.</td>
</tr>
<tr>
<td>path.enableDebugShape(assetManager,rootNode)</td><td>Shows a line that visualizes the path. Use this during development and for debugging so you see what you are doing.</td>
</tr>
<tr>
<td>path.disableDebugShape()</td><td>Hides the line that visualizes the path. Use this for the release build.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1769-2660] -->
</div>
<h2><a>MotionPathListener</a></h2>
<div>
<p>
You can hook interactions into a playing MotionPath. Register a MotionPathListener to the MotionPath to track whether way points have been reached, and then trigger a custom action. The onWayPointReach() method of the interface gives you access to the MotionTrack object <code>control</code>, and an integer value representing the current wayPointIndex.
</p>
<p>
In this example, you just print the status at every way point. In a game you could trigger actions here: Transformations, animations, sounds, game actions (attack, open door, etc).
</p>
<pre>path.addListener&#40; new MotionPathListener&#40;&#41; &#123;
public void onWayPointReach&#40;MotionTrack control, int wayPointIndex&#41; &#123;
if &#40;path.getNbWayPoints&#40;&#41; == wayPointIndex + 1&#41; &#123;
println&#40;control.getSpatial&#40;&#41;.getName&#40;&#41; + &quot; has finished moving. &quot;&#41;;
&#125; else &#123;
println&#40;control.getSpatial&#40;&#41;.getName&#40;&#41; + &quot; has reached way point &quot; + wayPointIndex&#41;;
&#125;
&#125;
&#125;&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:motionpath?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@ -0,0 +1,149 @@
<h1><a>Mouse Picking</a></h1>
<div>
<p>
Mouse picking means that the user clicks an object in the scene to select it, or to interact with it otherwise. Games use picking to implement aiming and shooting, casting spells, picking up objects, selecting targets, dragging and moving objects, etc. Mouse picking can be done using fixed crosshairs, or using the mouse pointer.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/mouse-picking.png">
</p>
<p>
See <a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">Input Handling</a> for details on how to define the necessary input triggers, input mappings, and input listeners.
</p>
</div>
<h2><a>Pick a Target Using Fixed Crosshairs</a></h2>
<div>
<p>
The following <code>pick target</code> input mapping implements an action that determines what a user clicked. It assumes that the mouse pointer is invisible and there are crosshairs painted in the center of the screen. It assumes that the user aims the crosshairs at an object in the scene and clicks. You use Ray Casting to identify the geometry that was picked by the user. Use use this method together with a first-person flyCam.
</p>
<ol>
<li><div> Activate the first-person camera: <code>flyCam.setEnabled(true);</code></div>
</li>
<li><div> Keep mouse pointer invisible using <code>inputManager.setCursorVisible(false)</code>.</div>
</li>
<li><div> Map the <code>pick target</code> action to a MouseButtonTrigger. </div>
</li>
<li><div> Implement the action in the Listener.</div>
</li>
</ol>
<p>
The following example rotates Spatials named &quot;Red Box&quot; or &quot;Blue Box&quot; when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
</p>
<pre> private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float intensity, float tpf&#41; &#123;
if &#40;name.equals&#40;&quot;pick target&quot;&#41;&#41; &#123;
// Reset results list.
CollisionResults results = new CollisionResults&#40;&#41;;
// Aim the ray from camera location in camera direction
// (assuming crosshairs in center of screen).
Ray ray = new Ray&#40;cam.getLocation&#40;&#41;, cam.getDirection&#40;&#41;&#41;;
// Collect intersections between ray and all nodes in results list.
rootNode.collideWith&#40;ray, results&#41;;
// Print the results so we see what is going on
for &#40;int i = 0; i &lt; results.size&#40;&#41;; i++&#41; &#123;
// For each “hit”, we know distance, impact point, geometry.
float dist = results.getCollision&#40;i&#41;.getDistance&#40;&#41;;
Vector3f pt = results.getCollision&#40;i&#41;.getContactPoint&#40;&#41;;
String target = results.getCollision&#40;i&#41;.getGeometry&#40;&#41;.getName&#40;&#41;;
System.out.println&#40;&quot;Selection #&quot; + i + &quot;: &quot; + target + &quot; at &quot; + pt + &quot;, &quot; + dist + &quot; WU away.&quot;&#41;;
&#125;
// 5. Use the results -- we rotate the selected geometry.
if &#40;results.size&#40;&#41; &gt; 0&#41; &#123;
// The closest result is the target that the player picked:
Geometry target = results.getClosestCollision&#40;&#41;.getGeometry&#40;&#41;;
// Here comes the action:
if&#40;target.getName&#40;&#41;.equals&#40;&quot;Red Box&quot;&#41;&#41;
target.rotate&#40;0, - intensity, 0&#41;;
else if&#40;target.getName&#40;&#41;.equals&#40;&quot;Blue Box&quot;&#41;&#41;
target.rotate&#40;0, intensity, 0&#41;;
&#125;
&#125; // else if ...
&#125;
&#125;;</pre>
</div>
<h2><a>Pick a Target Using the Mouse Pointer</a></h2>
<div>
<p>
The following <code>pick target</code> input mapping implements an action that determines what a user clicked. It assumes that the mouse pointer is visible, and the user aims the cursor at an object in the scene. You use ray casting to determine the geometry that was picked by the user.
</p>
<p>
<strong>Note:</strong> Picking with a visible pouse pointer implies that your application can no longer use the default flyCam where the MouseAxisTrigger rotates the camera. You have to deactivate the flyCam mappings and provide custom mappings. Either different inputs rotate the camera, or the camera is fixed.
</p>
<ol>
<li><div> Map the <code>pick target</code> action to a MouseButtonTrigger. </div>
</li>
<li><div> Make the mouse pointer visible using <code>inputManager.setCursorVisible(true)</code>.</div>
</li>
<li><div> Remap the inputs for camera rotation, or deactivate camera rotation. </div>
</li>
<li><div> Implement the action in the Listener.</div>
</li>
</ol>
<p>
The following example rotates Spatials named &quot;Red Box&quot; or &quot;Blue Box&quot; when they are clicked. Modify this code to do whatever your game needs to do with the identified target (shoot it, take it, move it, etc).
</p>
<pre>private AnalogListener analogListener = new AnalogListener&#40;&#41; &#123;
public void onAnalog&#40;String name, float intensity, float tpf&#41; &#123;
if &#40;name.equals&#40;&quot;pick target&quot;&#41;&#41; &#123;
// Reset results list.
CollisionResults results = new CollisionResults&#40;&#41;;
// Convert screen click to 3d position
Vector2f click2d = inputManager.getCursorPosition&#40;&#41;;
Vector3f click3d = cam.getWorldCoordinates&#40;new Vector2f&#40;click2d.x, click2d.y&#41;, 0f&#41;.clone&#40;&#41;;
Vector3f dir = cam.getWorldCoordinates&#40;new Vector2f&#40;click2d.x, click2d.y&#41;, 1f&#41;.subtractLocal&#40;click3d&#41;;
// Aim the ray from the clicked spot forwards.
Ray ray = new Ray&#40;click3d, dir&#41;;
// Collect intersections between ray and all nodes in results list.
rootNode.collideWith&#40;ray, results&#41;;
// (Print the results so we see what is going on:)
for &#40;int i = 0; i &lt; results.size&#40;&#41;; i++&#41; &#123;
// (For each “hit”, we know distance, impact point, geometry.)
float dist = results.getCollision&#40;i&#41;.getDistance&#40;&#41;;
Vector3f pt = results.getCollision&#40;i&#41;.getContactPoint&#40;&#41;;
String target = results.getCollision&#40;i&#41;.getGeometry&#40;&#41;.getName&#40;&#41;;
System.out.println&#40;&quot;Selection #&quot; + i + &quot;: &quot; + target + &quot; at &quot; + pt + &quot;, &quot; + dist + &quot; WU away.&quot;&#41;;
&#125;
// Use the results -- we rotate the selected geometry.
if &#40;results.size&#40;&#41; &gt; 0&#41; &#123;
// The closest result is the target that the player picked:
Geometry target = results.getClosestCollision&#40;&#41;.getGeometry&#40;&#41;;
// Here comes the action:
if &#40;target.getName&#40;&#41;.equals&#40;&quot;Red Box&quot;&#41;&#41; &#123;
target.rotate&#40;0, -intensity, 0&#41;;
&#125; else if &#40;target.getName&#40;&#41;.equals&#40;&quot;Blue Box&quot;&#41;&#41; &#123;
target.rotate&#40;0, intensity, 0&#41;;
&#125;
&#125;
&#125; // else if ...
&#125;
&#125;;</pre>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:node?do=showtag&amp;tag=tag%3Anode">node</a>,
<a href="/wiki/doku.php/tag:ray?do=showtag&amp;tag=tag%3Aray">ray</a>,
<a href="/wiki/doku.php/tag:click?do=showtag&amp;tag=tag%3Aclick">click</a>,
<a href="/wiki/doku.php/tag:collision?do=showtag&amp;tag=tag%3Acollision">collision</a>,
<a href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:mouse_picking?do=export_xhtmlbody">view online version</a></em></p>

@ -1,31 +1,69 @@
<h1><a
name="multiple_camera_views">Multiple Camera Views</a></h1><div
class="level1"><p> You can split the screen and look into the 3D scene from different camera angles at the same time. In this example, we create four views (2x2) with the same aspect ratio as the normal view, but half the size.</p><p> The packages used in this example are <code>com.jme3.renderer.Camera</code> and <code>com.jme3.renderer.ViewPort</code>. You can get the full sample code here: <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java">TestMultiViews.java</a></p></div><h2><a
name="set_up_the_first_view">Set up the First View</a></h2><div
class="level2"><p> We use the preconfigured Camera <code>cam</code> and <code>viewPort</code> from <code>SimpleApplication</code> for the first view.</p><pre>viewPort.setBackgroundColor&#40;ColorRGBA.Blue&#41;;
<h1><a>Multiple Camera Views</a></h1>
<div>
<p>
You can split the screen and look into the 3D scene from different camera angles at the same time. In this example, we create four views (2x2) with the same aspect ratio as the normal view, but half the size.
</p>
<p>
The packages used in this example are <code>com.jme3.renderer.Camera</code> and <code>com.jme3.renderer.ViewPort</code>. You can get the full sample code here: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java"><param name="text" value="<html><u>TestMultiViews.java</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<h2><a>Set up the First View</a></h2>
<div>
<p>
We use the preconfigured Camera <code>cam</code> and <code>viewPort</code> from <code>SimpleApplication</code> for the first view.
</p>
<pre>viewPort.setBackgroundColor&#40;ColorRGBA.Blue&#41;;
cam.setViewPort&#40;.5f, 1f, 0f, 0.5f&#41;; // resize the viewPort
cam.setLocation&#40;new Vector3f&#40;3.3212643f, 4.484704f, 4.2812433f&#41;&#41;;
cam.setRotation&#40;new Quaternion &#40;-0.07680723f, 0.92299235f, -0.2564353f, -0.27645364f&#41;&#41;;</pre><p> Place the main camera in the scene and rotate it in its start position.</p><p> We will have a detailed look at how we use setViewPort() to position and resize the default view later.</p></div><h2><a
name="set_up_three_additional_views">Set up Three Additional Views</a></h2><div
class="level2"><p> Here is the outline for how you create the three other cams and viewPorts (<a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java">Full code sample is here</a>.) In the code snippet, <code>cam_n</code> stand for <code>cam_2</code> - <code>cam_4</code>, respectively, same for <code>view_n</code>.</p><ol><li
class="level1"><div
class="li"> Clone the first cam to reuse its settings</div></li><li
class="level1"><div
class="li"> Resize and position the cam&#039;s viewPort with setViewPort() – details below.</div></li><li
class="level1"><div
class="li"> Place the cameras in the scene and rotate them.</div></li><li
class="level1"><div
class="li"> Create a main view for each camera</div></li><li
class="level1"><div
class="li"> Reset the cameras&#039; enabled statuses</div></li><li
class="level1"><div
class="li"> Attach the rootNode to be displayed to this view</div><ol><li
class="level2"><div
class="li"> It doesn&#039;t have to be rootNode, but that is the most common use case</div></li></ol></li><li
class="level1"><div
class="li"> You can set other optional view properties such as backgroundColor</div></li></ol><pre>Camera cam_n = cam.clone&#40;&#41;;
cam.setRotation&#40;new Quaternion &#40;-0.07680723f, 0.92299235f, -0.2564353f, -0.27645364f&#41;&#41;;</pre>
<p>
Place the main camera in the scene and rotate it in its start position.
</p>
<p>
We will have a detailed look at how we use setViewPort() to position and resize the default view later.
</p>
</div>
<h2><a>Set up Three Additional Views</a></h2>
<div>
<p>
Here is the outline for how you create the three other cams and viewPorts (<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java"><param name="text" value="<html><u>Full code sample is here</u></html>"><param name="textColor" value="blue"></object>.) In the code snippet, <code>cam_n</code> stand for <code>cam_2</code> - <code>cam_4</code>, respectively, same for <code>view_n</code>.
</p>
<ol>
<li><div> Clone the first cam to reuse its settings</div>
</li>
<li><div> Resize and position the cam&#039;s viewPort with setViewPort() – details below.</div>
</li>
<li><div> Place the cameras in the scene and rotate them.</div>
</li>
<li><div> Create a main view for each camera</div>
</li>
<li><div> Reset the cameras&#039; enabled statuses</div>
</li>
<li><div> Attach the rootNode to be displayed to this view</div>
<ol>
<li><div> It doesn&#039;t have to be rootNode, but that is the most common use case</div>
</li>
</ol>
</li>
<li><div> You can set other optional view properties such as backgroundColor</div>
</li>
</ol>
<pre>Camera cam_n = cam.clone&#40;&#41;;
cam_n.setViewPort&#40;...&#41;; // resize the viewPort
cam_n.setLocation&#40;new Vector3f&#40;...&#41;&#41;;
cam_n.setRotation&#40;new Quaternion&#40;...&#41;&#41;;
@ -33,16 +71,37 @@ cam_n.setRotation&#40;new Quaternion&#40;...&#41;&#41;;
ViewPort view_n = renderManager.createMainView&#40;&quot;View of camera #n&quot;, cam_n&#41;;
view_n.setClearEnabled&#40;true&#41;;
view_n.attachScene&#40;rootNode&#41;;
view_n.setBackgroundColor&#40;ColorRGBA.Black&#41;;</pre></div><h2><a
name="how_to_resize_and_position_the_viewports">How to resize and position the ViewPorts</a></h2><div
class="level2"><p> How does jme know which of the four views should appear where on the screen?</p><p> Imagine the view as a 1x1-sized box. By default, the settings is <code>cam.setViewPort(0f, 1f, 0f, 1f);</code>. This means the view takes up the whole box, from 0 to 1 left to right, and from 0 to 1 bottom to top.</p><p> In the <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java">code sample</a>, note the following four lines:</p><pre>cam.setViewPort&#40; 0.5f, 1.0f, 0.0f, 0.5f&#41;;
view_n.setBackgroundColor&#40;ColorRGBA.Black&#41;;</pre>
</div>
<h2><a>How to resize and position the ViewPorts</a></h2>
<div>
<p>
How does jme know which of the four views should appear where on the screen?
</p>
<p>
Imagine the view as a 1x1-sized box. By default, the settings is <code>cam.setViewPort(0f, 1f, 0f, 1f);</code>. This means the view takes up the whole box, from 0 to 1 left to right, and from 0 to 1 bottom to top.
</p>
<p>
In the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/renderer/TestMultiViews.java"><param name="text" value="<html><u>code sample</u></html>"><param name="textColor" value="blue"></object>, note the following four lines:
</p>
<pre>cam.setViewPort&#40; 0.5f, 1.0f, 0.0f, 0.5f&#41;;
...
cam_2.setViewPort&#40;0.0f, 0.5f, 0.0f, 0.5f&#41;;
...
cam_3.setViewPort&#40;0.0f, 0.5f, 0.5f, 1.0f&#41;;
...
cam_4.setViewPort&#40;0.5f, 1.0f, 0.5f, 1.0f&#41;;</pre><p> These viewport parameters are, in this order, the left - right - bottom - top extend of a camera&#039;s box on the screen. Note that we have set a few values to 0.5f – this is where we resize each view to half its default height and width.</p><pre>0.0 , 1.0 1.0 , 1.0
cam_4.setViewPort&#40;0.5f, 1.0f, 0.5f, 1.0f&#41;;</pre>
<p>
These viewport parameters are, in this order, the left - right - bottom - top extend of a camera&#039;s box on the screen. Note that we have set a few values to 0.5f – this is where we resize each view to half its default height and width.
</p>
<pre>0.0 , 1.0 1.0 , 1.0
+----+----+
| | |
|cam3|cam4|
@ -50,14 +109,35 @@ cam_4.setViewPort&#40;0.5f, 1.0f, 0.5f, 1.0f&#41;;</pre><p> These viewport param
| | |
|cam2|cam |
+----+----+
0.0 , 0.0 1.0 , 0.0</pre><p> Example: Cam3&#039;s rect extends from bottom-left (0.0 , 0.5) to top-right (0.5 , 1.0)</p><ul><li
class="level1"><div
class="li"> The left corner is at 0, and the right corner is 0.5 on the x axis.</div></li><li
class="level1"><div
class="li"> The bottom of the box is at 0.5 and the top at 1.0 on the y axis.</div></li></ul></div><h2><a
name="other_layouts">Other Layouts</a></h2><div
class="level2"><p> This layout shows 2x2 views. For a split screen you may want to lay out two views, one above the other, or one next to the other.</p><p> If you scale the views in a way so that the aspect ratio changes, the views will obviously be distorted. In these cases, create custom camera objects with the right aspect ratio (redefine the default cam).</p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:camera?do=showtag&amp;tag=tag%3Acamera">camera</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:multiple_camera_views?do=export_xhtmlbody">view online version</a></em></p>
0.0 , 0.0 1.0 , 0.0</pre>
<p>
Example: Cam3&#039;s rect extends from bottom-left (0.0 , 0.5) to top-right (0.5 , 1.0)
</p>
<ul>
<li><div> The left corner is at 0, and the right corner is 0.5 on the x axis. </div>
</li>
<li><div> The bottom of the box is at 0.5 and the top at 1.0 on the y axis.</div>
</li>
</ul>
</div>
<h2><a>Other Layouts</a></h2>
<div>
<p>
This layout shows 2x2 views. For a split screen you may want to lay out two views, one above the other, or one next to the other.
</p>
<p>
If you scale the views in a way so that the aspect ratio changes, the views will obviously be distorted. In these cases, create custom camera objects with the right aspect ratio (redefine the default cam).
</p>
<div><span>
<a href="/wiki/doku.php/tag:camera?do=showtag&amp;tag=tag%3Acamera">camera</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:multiple_camera_views?do=export_xhtmlbody">view online version</a></em></p>

@ -1,31 +1,107 @@
<h1><a
name="multithreading_optimization">Multithreading Optimization</a></h1><div
class="level1"><p> First, make sure you know what <a
href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> and <a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> are.</p><p> More complex games may feature complex mathematical operations or artificially intelligent calculations (such as path finding for several NPCs). If you make many time-intensive calls on the same thread (in the update loop), they will block one another, and thus slow down the game to a degree that makes it unplayable. If your game requires long running tasks, you should run them concurrently on separate threads, which speeds up the application considerably.</p><p> Often multithreading means having separate detached logical loops going on in parallel, which communicate about their state. (For example, one thread for AI, one Sound, one Graphics). However we recommend to use a global update loop for game logic, and do multithreading within that loop when it is appropriate. This approach scales way better to multiple cores and does not break up your code logic.</p><p> Effectively, each for-loop in the main update loop might be a chance for multithreading, if you can break it up into self-contained tasks.</p></div><h2><a
name="java_multithreading">Java Multithreading</a></h2><div
class="level2"><p> The java.util.concurrent package provides a good foundation for multithreading and dividing work into tasks that can be executed concurrently (hence the name). The three basic components are the Executor, Callable Objects (the tasks), and Future Objects. You can <a
href="http://download.oracle.com/javase/tutorial/essential/concurrency/">read about the concurrent package more here</a>, I will give just a short introduction.</p><ul><li
class="level1"><div
class="li"> A Callable is a class with a method call() that gets executed on a thread in the Executor. It represents one task (e.g, path finding).</div></li><li
class="level1"><div
class="li"> The Executor is one central object that manages the threads that are running to execute the Callables. Every time a Callable is added to the Executor, the Executor returns a Future object for it.</div></li><li
class="level1"><div
class="li"> A Future is an object that you use to check the status of an individual Callable&#039;s execution. It also gives you the return value in case one is created.</div></li></ul></div><h2><a
name="multithreading_in_jme3">Multithreading in jME3</a></h2><div
class="level2"><p> So how do we implement multithreading in jME3?</p><p> Let&#039;s take the example of a Control that controls an NPC Spatial. The NPC Control has to compute a lengthy pathfinding operation for each NPC. If we would execute the operations directly in the simpleUpdate() loop, it would block the game each time a NPC wants to move from A to B. Even if we move this behaviour into the update() method of a dedicated NPC Control, we would still get annoying freeze frames, because it still runs on the same update loop thread.</p><p> To avoid slowdown, we decide to keep the pathfinding operations in the NPC Control, <em>but execute it on another thread</em>.</p></div><h3><a
name="executor">Executor</a></h3><div
class="level3"><p> You create the executor object in a global AppState (or the initSimpleApp() method), in any case in a high-level place where multiple controls can access it.</p><pre>/* This constructor creates a new executor with a core pool size of 4. */
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor&#40;4&#41;;</pre><p> Pool size means the executor will keep four threads alive at any time. Having more threads in the pool means that more tasks can run concurrently. But a bigger pool only results in a speed gain if the PC can handle it! Allocating a pool that is uselessly large just wastes memory, so you need to find a good compromise: About the same to double the size of the number of cores in the computer makes sense.</p></div><h3><a
name="control_class_fields">Control Class Fields</a></h3><div
class="level3"><p> In the NPC Control, we create the individual objects that the thread manipulates. In our example case (the pathfinding control), the task is about locations and path arrays, so we need the following variables:</p><pre>//The vector to store the desired location in:
<h1><a>Multithreading Optimization</a></h1>
<div>
<p>
First, make sure you know what <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> and <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> are.
</p>
<p>
More complex games may feature complex mathematical operations or artificially intelligent calculations (such as path finding for several NPCs). If you make many time-intensive calls on the same thread (in the update loop), they will block one another, and thus slow down the game to a degree that makes it unplayable. If your game requires long running tasks, you should run them concurrently on separate threads, which speeds up the application considerably.
</p>
<p>
Often multithreading means having separate detached logical loops going on in parallel, which communicate about their state. (For example, one thread for AI, one Sound, one Graphics). However we recommend to use a global update loop for game logic, and do multithreading within that loop when it is appropriate. This approach scales way better to multiple cores and does not break up your code logic.
</p>
<p>
Effectively, each for-loop in the main update loop might be a chance for multithreading, if you can break it up into self-contained tasks.
</p>
</div>
<h2><a>Java Multithreading</a></h2>
<div>
<p>
The java.util.concurrent package provides a good foundation for multithreading and dividing work into tasks that can be executed concurrently (hence the name). The three basic components are the Executor, Callable Objects (the tasks), and Future Objects. You can <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://download.oracle.com/javase/tutorial/essential/concurrency/"><param name="text" value="<html><u>read about the concurrent package more here</u></html>"><param name="textColor" value="blue"></object>, I will give just a short introduction.
</p>
<ul>
<li><div> A Callable is a class with a method call() that gets executed on a thread in the Executor. It represents one task (e.g, path finding).</div>
</li>
<li><div> The Executor is one central object that manages the threads that are running to execute the Callables. Every time a Callable is added to the Executor, the Executor returns a Future object for it. </div>
</li>
<li><div> A Future is an object that you use to check the status of an individual Callable&#039;s execution. It also gives you the return value in case one is created.</div>
</li>
</ul>
</div>
<h2><a>Multithreading in jME3</a></h2>
<div>
<p>
So how do we implement multithreading in jME3?
</p>
<p>
Let&#039;s take the example of a Control that controls an NPC Spatial. The NPC Control has to compute a lengthy pathfinding operation for each NPC. If we would execute the operations directly in the simpleUpdate() loop, it would block the game each time a NPC wants to move from A to B. Even if we move this behaviour into the update() method of a dedicated NPC Control, we would still get annoying freeze frames, because it still runs on the same update loop thread.
</p>
<p>
To avoid slowdown, we decide to keep the pathfinding operations in the NPC Control, <em>but execute it on another thread</em>.
</p>
</div>
<h3><a>Executor</a></h3>
<div>
<p>
You create the executor object in a global AppState (or the initSimpleApp() method), in any case in a high-level place where multiple controls can access it.
</p>
<pre>/* This constructor creates a new executor with a core pool size of 4. */
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor&#40;4&#41;;</pre>
<p>
Pool size means the executor will keep four threads alive at any time. Having more threads in the pool means that more tasks can run concurrently. But a bigger pool only results in a speed gain if the PC can handle it! Allocating a pool that is uselessly large just wastes memory, so you need to find a good compromise: About the same to double the size of the number of cores in the computer makes sense.
</p>
</div>
<h3><a>Control Class Fields</a></h3>
<div>
<p>
In the NPC Control, we create the individual objects that the thread manipulates. In our example case (the pathfinding control), the task is about locations and path arrays, so we need the following variables:
</p>
<pre>//The vector to store the desired location in:
Vector3f desiredLocation = new Vector3f&#40;&#41;;
//The MyWayList object that contains the result waylist:
MyWayList wayList = null;
//The future that is used to check the execution status:
Future future = null;</pre><p> Here we also created the Future variable to track the state of this task.</p></div><h3><a
name="control_update_method">Control Update() Method</a></h3><div
class="level3"><p> Next let&#039;s look at the update() call of the Control where the time-intensive task starts. In our example, the task is the <code>findWay</code> Callable (which contains the pathfinding process). So instead of spelling out the pathfinding process in the Control&#039;s update() loop, we start the process via <code>future = executor.submit(findWay);</code>.</p><pre>public void update&#40;float tpf&#41; &#123;
Future future = null;</pre>
<p>
Here we also created the Future variable to track the state of this task.
</p>
</div>
<h3><a>Control Update() Method</a></h3>
<div>
<p>
Next let&#039;s look at the update() call of the Control where the time-intensive task starts. In our example, the task is the <code>findWay</code> Callable (which contains the pathfinding process). So instead of spelling out the pathfinding process in the Control&#039;s update() loop, we start the process via <code>future = executor.submit(findWay);</code>.
</p>
<pre>public void update&#40;float tpf&#41; &#123;
try&#123;
//If we have no waylist and not started a callable yet, do so!
if&#40;wayList == null &amp;&amp; future == null&#41;&#123;
@ -54,13 +130,48 @@ class="level3"><p> Next let&#039;s look at the update() call of the Control wher
if&#40;wayList != null&#41;&#123;
//.... Success! Let's process the wayList and move the NPC...
&#125;
&#125;</pre><p> Note how this logic makes its decision based on the Future object.</p><p> Remember not to mess with the class fields after starting the thread, because they are being accessed and modified on the new thread. In more obvious terms: You cannot change the &quot;desired location&quot; of the NPC while the path finder is calculating a different path. You have to cancel the current Future first.</p></div><h3><a
name="the_callable">The Callable</a></h3><div
class="level3"><p> The next code sample shows the Callable that is dedicated to performing the long-running task (here, wayfinding). This is the task that used to block the rest of the application, and is now executed on a thread of its own. You implement the task in the Callable always in an inner method named <code>call()</code>.</p><p> The task code in the Callable should be self-contained! It should not write or read any data of objects that are managed by the scene graph or OpenGL thread directly. Even reading locations of Spatials can be problematic! So ideally all data that is needed for the wayfinding process should be available to the new thread when it starts already, possibly in a cloned version so no concurrent access to the data happens.</p><p> In reality, you might need access to the game state. If you must read or write a current state from the scene graph, you must have a clone of the data in your thread. There are only two ways:</p><ul><li
class="level1"><div
class="li"> Use the execution queue <code>application.enqueue()</code> to create a sub-thread that clones the info. Only disadvantage is, it may be slower. <br/> The example below gets the <code>Vector3f location</code> from the scene object <code>mySpatial</code> using this way.</div></li><li
class="level1"><div
class="li"> Create a separate World class that allows safe access to its data via synchronized methods to access the scene graph. Alternatively it can also internally use <code>application.enqueue()</code>. <br/> The following example gets the object <code>Data data = myWorld.getData();</code> using this way.</div></li></ul><p> These two ways are thread-safe, they don&#039;t mess up the game logic, and keep the Callable code readable.</p><pre>// A self-contained time-intensive task:
&#125;</pre>
<p>
Note how this logic makes its decision based on the Future object.
</p>
<p>
Remember not to mess with the class fields after starting the thread, because they are being accessed and modified on the new thread. In more obvious terms: You cannot change the &quot;desired location&quot; of the NPC while the path finder is calculating a different path. You have to cancel the current Future first.
</p>
</div>
<h3><a>The Callable</a></h3>
<div>
<p>
The next code sample shows the Callable that is dedicated to performing the long-running task (here, wayfinding). This is the task that used to block the rest of the application, and is now executed on a thread of its own. You implement the task in the Callable always in an inner method named <code>call()</code>.
</p>
<p>
The task code in the Callable should be self-contained! It should not write or read any data of objects that are managed by the scene graph or OpenGL thread directly. Even reading locations of Spatials can be problematic! So ideally all data that is needed for the wayfinding process should be available to the new thread when it starts already, possibly in a cloned version so no concurrent access to the data happens.
</p>
<p>
In reality, you might need access to the game state. If you must read or write a current state from the scene graph, you must have a clone of the data in your thread. There are only two ways:
</p>
<ul>
<li><div> Use the execution queue <code>application.enqueue()</code> to create a sub-thread that clones the info. Only disadvantage is, it may be slower. <br/>
The example below gets the <code>Vector3f location</code> from the scene object <code>mySpatial</code> using this way.</div>
</li>
<li><div> Create a separate World class that allows safe access to its data via synchronized methods to access the scene graph. Alternatively it can also internally use <code>application.enqueue()</code>. <br/>
The following example gets the object <code>Data data = myWorld.getData();</code> using this way.</div>
</li>
</ul>
<p>
These two ways are thread-safe, they don&#039;t mess up the game logic, and keep the Callable code readable.
</p>
<pre>// A self-contained time-intensive task:
private Callable&lt;MyWayList&gt; findWay = new Callable&lt;MyWayList&gt;&#40;&#41;&#123;
public MyWayList call&#40;&#41; throws Exception &#123;
&nbsp;
@ -79,14 +190,26 @@ private Callable&lt;MyWayList&gt; findWay = new Callable&lt;MyWayList&gt;&#40;&#
&nbsp;
return wayList;
&#125;
&#125;;</pre></div><h2><a
name="conclusion">Conclusion</a></h2><div
class="level2"><p> The cool thing about this appraoch is that every entity creates one self-contained Callable for the Executor, and they are all executed in parallel. In theory, you can have one thread per entity without changing anything else but the settings of the executor.</p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:loop?do=showtag&amp;tag=tag%3Aloop">loop</a>, <a
href="/wiki/doku.php/tag:game?do=showtag&amp;tag=tag%3Agame">game</a>, <a
href="/wiki/doku.php/tag:performance?do=showtag&amp;tag=tag%3Aperformance">performance</a>, <a
href="/wiki/doku.php/tag:state?do=showtag&amp;tag=tag%3Astate">state</a>, <a
href="/wiki/doku.php/tag:states?do=showtag&amp;tag=tag%3Astates">states</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading?do=export_xhtmlbody">view online version</a></em></p>
&#125;;</pre>
</div>
<h2><a>Conclusion</a></h2>
<div>
<p>
The cool thing about this appraoch is that every entity creates one self-contained Callable for the Executor, and they are all executed in parallel. In theory, you can have one thread per entity without changing anything else but the settings of the executor.
</p>
<div><span>
<a href="/wiki/doku.php/tag:loop?do=showtag&amp;tag=tag%3Aloop">loop</a>,
<a href="/wiki/doku.php/tag:game?do=showtag&amp;tag=tag%3Agame">game</a>,
<a href="/wiki/doku.php/tag:performance?do=showtag&amp;tag=tag%3Aperformance">performance</a>,
<a href="/wiki/doku.php/tag:state?do=showtag&amp;tag=tag%3Astate">state</a>,
<a href="/wiki/doku.php/tag:states?do=showtag&amp;tag=tag%3Astates">states</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading?do=export_xhtmlbody">view online version</a></em></p>

@ -1,150 +1,443 @@
<h1><a
name="multiplayer_networking">Multiplayer Networking</a></h1><div
class="level1"><p> This provides an overview of the new SpiderMonkey <acronym
title="Application Programming Interface">API</acronym> and a path for migrating from the old, now deprecated, <acronym
title="Application Programming Interface">API</acronym> to the newer version. Much has changed.</p><p> The <a
href="/com/jme3/gde/core/docs/spidermonkey.html">original SpiderMonkey</a> implementation was a good concept and a clever implementation but suffered under the weight of rapid patches and some creeping design deficit. In the end, there were enough small problems, long-term maintenance issues, and limitations that a newer design was warranted.</p><p> Some things will be very similar but others have changed very much. Hopefully for the better.</p></div><h2><a
name="overview">Overview</a></h2><div
class="level2"><p> Most of the new SpiderMonkey <acronym
title="Application Programming Interface">API</acronym> now exists as a set of interfaces and helper classes in the &#039;com.jme3.network&#039; package. For most users, this package and the &#039;message&#039; package will be all they need to worry about. The &#039;base&#039; and &#039;kernel&#039; packages only come into play when implementing custom network transports or alternate client/server protocols (<em>which are now possible</em>).</p><p> Clients and Servers can be created from the factory methods on the Network helper class. Once a Server instance is created and started, it can accept remote connections from Clients. The Client objects represent the client-side of a client→server connection. Within the Server, these are HostedConnections. This is a distinct change from the old <acronym
title="Application Programming Interface">API</acronym>.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Client</th><th
class="col1 leftalign"></th><th
class="col2 leftalign"> Server</th></tr><tr
class="row1"><td
class="col0"> com.jme3.network.Client</td><td
class="col1"> ←→</td><td
class="col2"> com.jme3.network.HostedConnection</td></tr></table></div><p> HostedConnections can hold application defined client-specific session attributes that the server-side listeners and services can use to track player information, etc..</p><p> MessageListeners can be registered with either the Client or the Server to be notified when new messages arrive. As before, these listeners can be registered to be notified about only specific
types of messages.</p><p> ClientStateListeners can be registered with a Client to detect changes in connection state.</p><p> ConnectionListeners can be registered with a Server to be notified about HostedConnection arrivals and removals.</p></div><h2><a
name="what_s_gone">What&#039;s Gone?</a></h2><div
class="level2"><p> All of &#039;connection&#039;, &#039;events&#039;, &#039;queue&#039;, &#039;service&#039;, &#039;streaming&#039;, and &#039;sync&#039; are now deprecated. The &#039;service&#039;, &#039;streaming&#039;, and &#039;sync&#039; packages were too difficult to easily port to the new <acronym
title="Application Programming Interface">API</acronym> and would have required additional code review for thread-related issues. Since the service manager model has _not_ been ported and will likely live on in a different way, it was better to let these go until better solutions evolve. For example, streaming is probably better done more tightly integrated with the core <acronym
title="Application Programming Interface">API</acronym> and as actual java.io streams.</p></div><h2><a
name="migration">Migration</a></h2><div
class="level2"></div><h3><a
name="package_class_imports">Package/Class Imports</a></h3><div
class="level3"><p> As a first pass, use the following table for conversion and then see specific class notes.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0"> Old Class</th><th
class="col1"> New Class</th></tr><tr
class="row1"><td
class="col0">com.jme3.network.connection.Client</td><td
class="col1"> com.jme3.network.Client or com.jme3.network.HostedConnection</td></tr><tr
class="row2"><td
class="col0">com.jme3.network.connection.Server</td><td
class="col1"> com.jme3.network.Server</td></tr><tr
class="row3"><td
class="col0">com.jme3.network.event.MessageListener</td><td
class="col1"> com.jme3.network.MessageListener</td></tr><tr
class="row4"><td
class="col0">com.jme3.network.event.ConnectionListener</td><td
class="col1"> com.jme3.network.ClientStateListener or com.jme3.network.ConnectionListener</td></tr><tr
class="row5"><td
class="col0">com.jme3.network.event.MessageAdapter</td><td
class="col1"> no equivalent class, implement MessageListener directly</td></tr><tr
class="row6"><td
class="col0">com.jme3.network.event.ConnectionAdapter</td><td
class="col1"> no equivalent class, implement ClientStateListener or ConnectionListener directly</td></tr><tr
class="row7"><td
class="col0">com.jme3.network.message.Message</td><td
class="col1"> if used as a reference and not a superclass, com.jme3.network.Message. The base class stays the same for message subclasses.</td></tr></table></div><p> Doing all of those changes will certainly break your build… so now let&#039;s fix it.</p></div><h3><a
name="client_and_messagelistener">Client and MessageListener</a></h3><div
class="level3"><p> This class is the hardest migration to perform. Do not get discouraged.</p><p> The old version used com.jme3.network.connection.Client for both client side and server side. So, depending on context, these references will either change to com.jme3.network.Client or com.jme3.network.HostedConnection. In the case where calling code is not client or server specific, then there is also the common com.jme3.network.MessageConnection interface.</p><p> In general, the actual client changes are of one of the following to types:</p><pre> Client client = new Client&#40; host, port &#41;;
&nbsp;
...becomes...
&nbsp;
Client client = Network.connectToServer&#40; host, port &#41;; </pre><p> In the delayed connection case:</p><pre> Client client = new Client&#40;&#41;;
...
client.connect&#40; host, port &#41;;
&nbsp;
...becomes...
&nbsp;
NetworkClient client = Network.createClient&#40;&#41;;
...
client.connectToServer&#40; host, port &#41;;</pre><p> NetworkClient is a Client. The rest of your code can just refer to Client.</p><p> Those are the easy changes. The trickier ones are related to the MessageListeners.</p></div><h4><a
name="messagelistener">MessageListener</a></h4><div
class="level4"><p> By now you&#039;ve figured out that all of your MessageListeners are broken because the new method signature is different. The source of a message is no longer stored with the message and is instead provided to the MessageListener.</p><p> Depending on whether your MessageListener is being added to the Client or the Server, it will need to refer to either com.jme3.network.Client or com.jme3.network.HostedConnection in its messageReceived(), respectively. The MessageListener interface is generically typed to help make sure the right listener goes where it&#039;s supposed to and so the listener implementations don&#039;t have to cast all the time.</p><pre>// An example client-specific listener
public class MyClientListener implements MessageListener&lt;Client&gt; &#123;
&nbsp;
public void messageReceived&#40; Client source, Message m &#41; &#123;
...do stuff...
&#125;
&#125;
&nbsp;
// And example server-specific listener
public class MyServerListener implements MessageListener&lt;HostedConnection&gt; &#123;
&nbsp;
public void messageReceived&#40; HostedConnection source, Message m &#41; &#123;
...do stuff...
&#125;
&#125;
&nbsp;
// A client or server listener
public class MyGenericListener implements MessageListener&lt;MessageConnection&gt; &#123;
&nbsp;
public void messageReceived&#40; MessageConnection source, Message m &#41; &#123;
... do limited stuff....
&#125;
&#125;</pre><p> Your listeners will fall into one of those three categories.</p><p><p><div
class="noteclassic">Several of the old MessageListener&#039;s methods have gone away. The object-based methods didn&#039;t fit with the new <acronym
title="Application Programming Interface">API</acronym> and messageSent() seemed of little utility. It could be resurrected if there is demand.</div></p></p></div><h4><a
name="client_method_changes">Client method changes</a></h4><div
class="level4"><p> Some of the methods on the old Client class have changed or been removed. Here is a basic summary:</p><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0"> Old Method</th><th
class="col1"> New Method</th></tr><tr
class="row1"><td
class="col0"> Client.disconnect()</td><td
class="col1"> Client.close() or HostedConnection.close(reason)</td></tr><tr
class="row2"><td
class="col0"> Client.kick(reason)</td><td
class="col1"> HostedConnection.close(reason)</td></tr><tr
class="row3"><td
class="col0"> Client.getClientID()</td><td
class="col1"> Client.getId() or HostedConnection.getId()</td></tr><tr
class="row4"><td
class="col0"> Client.get/setPlayerID()</td><td
class="col1"> no equivalent</td></tr><tr
class="row5"><td
class="col0"> Client.get/setLabel()</td><td
class="col1"> no equivalent</td></tr></table></div></div><h4><a
name="no_ioexceptions">No IOExceptions</a></h4><div
class="level4"><p> After you&#039;ve done all of that, the compiler will be complaining about the fact that send(), broadcast(), etc. no longer throw IOException. So remove all of those try/catch blocks.<p><div
class="noteclassic">The truth is that even in the old <acronym
title="Application Programming Interface">API</acronym>, expecting a real IOException from these methods was unreasonable because often times the message was queued and actually sent later by a separate thread. The new <acronym
title="Application Programming Interface">API</acronym> assumes that all underlying transports will operate this way and so forgoes the artificial annoyance or sense of security provided by these &#039;throws&#039; clauses. It also simplifies the calling code a great deal.</div></p></p><p> Only <acronym
title="Application Programming Interface">API</acronym> methods that actually perform direct IO (such as the Network.connectToServer() and NetworkClient.connectToServer() methods) will ever be declared to throw IOException.</p></div><h3><a
name="messagegetclient_and_messagegetconnection">Message.getClient() and Message.getConnection()</a></h3><div
class="level3"><p> This is important enough to deserve its own sub-heading because your code <strong>will</strong> break if you use these as they now return null. Any reason for calling them is now provided directly to the MessageListener in the form of the source Client or source HostedConnection.</p></div><h3><a
name="client_id_and_player_id">Client ID and Player ID</a></h3><div
class="level3"><p> The ID of the Client and HostedConnection are now the same at both ends of a connection and the ID is given out authoritatively by the hosting Server. This removes some of the inconsistency on when to use the old player ID and when to use the old client ID as the new client ID serves both purposes. This leaves the game to be able to define its own player ID based on whatever user criteria it wants.</p><p><p><div
class="noteclassic">Many of the reasons for accessing the client ID on the server can now be taken care of using the session attributes on HostedConnection. It seems like a common use-case for these IDs was to look-up player/client-specific information in a java.util.Map. This information can now be set directly on the HostedConnection.</div></p></p></div><h3><a
name="comjme3networkeventconnectionlistener">com.jme3.network.event.ConnectionListener</a></h3><div
class="level3"><p> Along with the shift from not using the same object at both ends of the client connection was a shift in the interfaces that are notified about those ends.</p><p> On the client, there is now com.jme3.network.ClientStateListener which is notified when the client fully connects to the server (including any internal handshaking) and when the client is disconnected.</p><p> On the server, com.jme3.network.ConnectionListener will be notified whenever new HostedConnections are added or removed. This listener isn&#039;t notified until the connection is fully setup (including any internal handshaking).</p><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0"> Old Method</th><th
class="col1"> New Method</th></tr><tr
class="row1"><td
class="col0"> clientConnected(Client)</td><td
class="col1"> connectionAdded(Server,HostedConnection)</td></tr><tr
class="row2"><td
class="col0"> clientDisconnected(Client)</td><td
class="col1"> connectionRemoved(Server,HostedConnection)</td></tr></table></div></div><h2><a
name="why_am_i_doing_this_again">Why am I doing this again?</a></h2><div
class="level2"><p> As you&#039;ve seen above, there are quite a few changes necessary to migrate to the new <acronym
title="Application Programming Interface">API</acronym>. You might be asking yourself if it&#039;s worth the trouble.</p><p> The bottom line is that the old architecture had threading and stability issues that just couldn&#039;t be fixed in any reasonable way. Some were minor, others kind of severe… and they combined to make trouble. If you&#039;ve ever wondered why sometimes your clients connect and then the network connection hangs or stops sending data. Or if you&#039;ve ever wondered why UDP/unreliable messages get corrupted or somehow won&#039;t deserialize properly then you&#039;ve run into some of these issues.</p><p> Moreover, the lack of thread safety meant that user code sometimes had to do some strange and/or complicated work-arounds. The goal should be that the <acronym
title="Application Programming Interface">API</acronym> should just work like it looks like it will with a minimum of hassle.</p><p> The new architecture is built from the ground up for threading stability and for a clean separation between the public <acronym
title="Application Programming Interface">API</acronym>, the message passing layer, and the underlying network transport implementations. You should be able to throw all kinds of stuff at it that would make the old system fall over and it should just hum along.</p><p> There will certainly be some growing pains as we work the kinks out of the new system but it is already much more stable in even the most basic of stress tests.</p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:network?do=showtag&amp;tag=tag%3Anetwork">network</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:networking?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>SpiderMonkey: Multi-Player Networking</a></h1>
<div>
<p>
This document introduces you to the SpiderMonkey networking <acronym title="Application Programming Interface">API</acronym>. A multi-player game is made up of clients and a server.
</p>
<ul>
<li><div> One central server (a headless SimpleApplication) coordinates the game in the background.</div>
</li>
<li><div> Each player runs a game client (a standard SimpleApplications) and connects to the central server.</div>
</li>
</ul>
<p>
Each Client informs the Server about its player&#039;s moves and actions. The Server centrally collects the game state and broadcasts the state info back to all connected clients. This way all clients share the same game world and can display it to their players from their perspective.
</p>
</div>
<h2><a>SpiderMonkey API Overview</a></h2>
<div>
<p>
The SpiderMonkey <acronym title="Application Programming Interface">API</acronym> is a set of interfaces and helper classes in the &#039;com.jme3.network&#039; package. For most users, this package and the &#039;message&#039; package is all they need to worry about. (The &#039;base&#039; and &#039;kernel&#039; packages only come into play when implementing custom network transports or alternate client/server protocols, which is now possible).
</p>
<p>
The SpiderMonkey <acronym title="Application Programming Interface">API</acronym> assists you in creating a Server, Clients, and Messages. Once a Server instance is created and started, the Server accepts remote connections from Clients, and you can send and receive Messages. Client objects represent the client-side of the client-server connection. Within the Server, these Client objects are referred to as HostedConnections. HostedConnections can hold application-defined client-specific session attributes that the server-side listeners and services can use to track player information, etc.
</p>
<div><table>
<tr>
<th> Seen from the Client </th><th> </th><th> Seen from the Server </th>
</tr>
<tr>
<td> com.jme3.network.Client </td><td> == </td><td> com.jme3.network.HostedConnection </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1580-1698] -->
<p>
You can register several types of listeners to be notified of changes.
</p>
<ul>
<li><div> MessageListeners on both the Client and the Server are notified when new messages arrive. You can use MessageListeners to be notified about only specific types of messages.</div>
</li>
<li><div> ClientStateListeners inform the Client of changes in its connection state, e.g. when the client gets kicked from the server.</div>
</li>
<li><div> ConnectionListeners inform the Server about HostedConnection arrivals and removals, e.g. if a client joins or quits.</div>
</li>
</ul>
</div>
<h2><a>Client and Server</a></h2>
<div>
</div>
<h3><a>Creating a Server</a></h3>
<div>
<p>
A com.jme3.network.Server is a headless com.jme3.app.SimpleApplication. Headless means that the update loop runs, but the application does not open a window and does not listen to direct user input.
</p>
<pre>ServerMain app = new ServerMain&#40;&#41;;
app.start&#40;JmeContext.Type.Headless&#41;;</pre>
<p>
Create a Server in the simpleInitApp() method and specify a communication port, for example 6143.
</p>
<pre>Server myServer = Network.createServer&#40;6143&#41;;
myServer.start&#40;&#41;;</pre>
<p>
The server is ready to accept clients. Let&#039;s create one.
</p>
</div>
<h3><a>Creating a Client</a></h3>
<div>
<p>
A com.jme3.network.Client is a standard com.jme3.app.SimpleApplication.
</p>
<pre>ClientMain app = new ClientMain&#40;&#41;;
app.start&#40;JmeContext.Type.Display&#41;; // standard type</pre>
<p>
Create a Client in the simpleInitApp() method and specify the servers IP address, and the same communication port as for the server, here 6143.
</p>
<pre>Client myClient = Network.connectToServer&#40;&quot;localhost&quot;, 6143&#41;;
myClient.start&#40;&#41;;</pre>
<p>
The server address can be in the format &quot;localhost&quot;, &quot;127.0.0.1&quot; (for local testing) or “123.456.78.9” (the IP address of a real server).
</p>
</div>
<h3><a>Getting Info About a Client</a></h3>
<div>
<p>
The server refers to a connected client as com.jme3.network.HostedConnection. The server can get info about clients as follows:
</p>
<div><table>
<tr>
<th>Accessor</th><th>Purpose</th>
</tr>
<tr>
<td>myServer.getConnection(0)</td><td>Server gets the first etc connected HostedConnection object.</td>
</tr>
<tr>
<td>myServer.getConnections()</td><td>Server gets a collection of all connected HostedConnection objects.</td>
</tr>
<tr>
<td>myServer.getConnections().size()</td><td>Server gets the number of all connected HostedConnection objects.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [3563-3867] -->
<p>
Your game can define its own player ID based on whatever user criteria you want. If the server needs to look up player/client-specific information, it can store this information directly on the HostedConnection object:
</p>
<div><table>
<tr>
<th>Accessor</th><th>Purpose</th>
</tr>
<tr>
<td> conn.setAttribute(&quot;MyState&quot;, new MyState()); </td><td> Server can change an attribute of the HostedConnection. </td>
</tr>
<tr>
<td> MyState state = conn.getAttribute(&quot;MyState&quot;)</td><td> Server can read an attribute of the HostedConnection. </td>
</tr>
</table></div>
<!-- EDIT3 TABLE [4089-4318] -->
</div>
<h2><a>Messaging</a></h2>
<div>
</div>
<h3><a>Creating Message Types</a></h3>
<div>
<p>
Each message represents data you want to transmit, for instance transformation updates or game actions. For each message type, create a message class that extends com.jme3.network.AbstractMessage. Use the @Serializable annotation from com.jme3.network.serializing.Serializable and create an empty default constructor. Custom constructors, fields, and methods are up to you and depend on the message data that you want to transmit.
</p>
<pre>@Serializable
public class HelloMessage extends AbstractMessage &#123;
private String hello; // message data
public HelloMessage&#40;&#41; &#123;&#125; // empty constructor
public HelloMessage&#40;String s&#41; &#123; hello = s; &#125; // custom constructor
&#125;</pre>
<p>
Register each message type to the com.jme3.network.serializing.Serializer, in both server and client.
</p>
<pre>Serializer.registerClass&#40;HelloMessage.class&#41;;</pre>
</div>
<h3><a>Reacting to Messages</a></h3>
<div>
<p>
After a message was received, a listener responds to it. The listener can access fields of the message, and send messages back. Implement responses in the two Listeners’ messageReceived() methods for each message type.
</p>
</div>
<h4><a>ClientListener.java</a></h4>
<div>
<p>
Create one ClientListener.java and make it extend <code>com.jme3.network.MessageListener</code>.
</p>
<pre>public class ClientListener implements MessageListener&lt;Client&gt; &#123;
public void messageReceived&#40;Client source, Message message&#41; &#123;
if &#40;message instanceof HelloMessage&#41; &#123;
// do something with the message
HelloMessage helloMessage = &#40;HelloMessage&#41; message;
System.out.println&#40;&quot;Client #&quot;+source.getId&#40;&#41;+&quot; received: '&quot;+helloMessage.getSomething&#40;&#41;+&quot;'&quot;&#41;;
&#125; // else...
&#125;</pre>
<p>
For each message type, register a client listener to the client.
</p>
<pre>myClient.addMessageListener&#40;new ClientListener&#40;&#41;, HelloMessage.class&#41;;</pre>
</div>
<h4><a>ServerListener.java</a></h4>
<div>
<p>
Create one ServerListener.java and make it extend <code>com.jme3.network.MessageListener</code>.
</p>
<pre>public class ServerListener implements MessageListener&lt;HostedConnection&gt; &#123;
public void messageReceived&#40;HostedConnection source, Message message&#41; &#123;
if &#40;message instanceof HelloMessage&#41; &#123;
// do something with the message
HelloMessage helloMessage = &#40;HelloMessage&#41; message;
System.out.println&#40;&quot;Server received '&quot; +helloMessage.getSomething&#40;&#41; +&quot;' from client #&quot;+source.getId&#40;&#41; &#41;;
&#125; // else....
&#125;</pre>
<p>
For each message type, register a server listener to the server:
</p>
<pre>myServer.addMessageListener&#40;new ServerListener&#40;&#41;, HelloMessage.class&#41;;</pre>
</div>
<h3><a>Creating and Sending Messages</a></h3>
<div>
<p>
A client can send a message to the server:
</p>
<pre>Message message = new HelloMessage&#40;&quot;Hello World!&quot;&#41;;
myClient.send&#40;message&#41;;</pre>
<p>
The server can broadcast a message to all HostedConnection (clients):
</p>
<pre>Message message = new HelloMessage&#40;&quot;Welcome!&quot;&#41;;
myServer.broadcast&#40;message&#41;;</pre>
<p>
Using com.jme3.network.Filters, the server can send a message to specific HostedConnection (conn1, conn2, conn3), or to all but a few HostedConnections (not to conn4).
</p>
<pre>myServer.broadcast&#40; Filters.in&#40; conn1, conn2, conn3 &#41;, message &#41;;
myServer.broadcast&#40; Filters.notEqualTo&#40; conn4 &#41;, message &#41;;</pre>
</div>
<h2><a>Identification and Rejection</a></h2>
<div>
<p>
The ID of the Client and HostedConnection are the same at both ends of a connection. The ID is given out authoritatively by the Server.
</p>
<pre>... myClient.getId&#40;&#41; ...</pre>
<p>
A server has a game version and game name. Each client expects to communicate with a server with a certain game name and version. Test first whether the game name matches, and then whether game version matches, before sending any messages! If they do not match, you should refuse to connect, because the client and server will not be able to communicate.
</p>
<div><table>
<tr>
<th>Accessor</th><th>Purpose</th>
</tr>
<tr>
<td> myServer.setName() </td><td> Specify the game name (free-form String) </td>
</tr>
<tr>
<td> myServer.setVersion() </td><td> Specify the game version (int) </td>
</tr>
<tr>
<td> myClient.getGameName() </td><td> Client gets the name of the server it is connected to. </td>
</tr>
<tr>
<td> myClient.getVersion() </td><td> Client gets the version of the server it is connected to. </td>
</tr>
</table></div>
<!-- EDIT4 TABLE [8113-8426] -->
<p>
<strong>Tip:</strong> Your game defines its own attributs, such as player ID, based on whatever criteria you want. If you want to look up player/client-specific information, you can set this information directly on the Client/HostedConnection (see Getting Info About a Client).
</p>
</div>
<h2><a>Closing Clients and Server Cleanly</a></h2>
<div>
</div>
<h3><a>Closing a Client</a></h3>
<div>
<p>
You must override the client&#039;s destroy() method to close the connection cleanly when the player quits the client:
</p>
<pre> @Override
public void destroy&#40;&#41; &#123;
myClient.close&#40;&#41;;
super.destroy&#40;&#41;;
&#125;</pre>
</div>
<h3><a>Closing a Server</a></h3>
<div>
<p>
You must override the server&#039;s destroy() method to close the connection when the server quits:
</p>
<pre> @Override
public void destroy&#40;&#41; &#123;
myServer.close&#40;&#41;;
super.destroy&#40;&#41;;
&#125;</pre>
</div>
<h3><a>Kicking a Client</a></h3>
<div>
<p>
The server can kick a HostedConnection to make it disconnect. You should provide a String with further info (an explanation to the user what happened) for the server to send along. This info message can be used (displayed to the user) by a ClientStateListener. (See below)
</p>
<pre>conn.close&#40;&quot;We kick cheaters.&quot;&#41;;</pre>
</div>
<h2><a>Listening to Connection Notification</a></h2>
<div>
<p>
The server and clients are notified about connection changes.
</p>
</div>
<h3><a>ClientStateListener</a></h3>
<div>
<p>
The com.jme3.network.ClientStateListener notifies the Client when the Client has fully connected to the server (including any internal handshaking), and when the Client is kicked (disconnected) from the server.
</p>
<div><table>
<tr>
<th> ClientStateListener interface </th><th> Purpose </th>
</tr>
<tr>
<td> clientConnected(Client c) </td><td> Implement here what happens as soon as this clients has fully connected to the server. </td>
</tr>
<tr>
<td> clientDisconnected(Client c, DisconnectInfo info) </td><td> Implement here what happens after the server kicks this client. For example, display the DisconnectInfo to the user. </td>
</tr>
</table></div>
<!-- EDIT5 TABLE [9930-10265] -->
<p>
Implement the ClientStateListener interface in the Client, and then register it:
</p>
<pre>myClient.addClientStateListener&#40;this&#41;;</pre>
</div>
<h3><a>ConnectionListener</a></h3>
<div>
<p>
The com.jme3.network.ConnectionListener notifies the Server whenever new HostedConnections (clients) come and go. The listener notifies the server after the Client connection is fully established (including any internal handshaking).
</p>
<div><table>
<tr>
<th> ConnectionListener interface </th><th> Purpose </th>
</tr>
<tr>
<td> connectionAdded(Server s, HostedConnection c) </td><td> Implemenent here what happens after a new HostedConnection has joined the Server. </td>
</tr>
<tr>
<td> connectionRemoved(Server s, HostedConnection c) </td><td> Implement here what happens after a HostedConnection has left. E.g. a player has quit the game and the server removes his character. </td>
</tr>
</table></div>
<!-- EDIT6 TABLE [10672-11035] -->
<p>
Implement the ConnectionListener in the Server, and register it.
</p>
<pre>myServer.addConnectionListener&#40;this&#41;;</pre>
</div>
<h2><a>UDP versus TCP</a></h2>
<div>
<p>
SpiderMonkey supports both UDP (unreliable, fast) and TCP (reliable, slow) transport of messages.
</p>
<pre>message1.setReliable&#40;true&#41;; // TCP
message2.setReliable&#40;false&#41;; // UDP</pre>
<ul>
<li><div> Choose reliable and slow transport for messages, if you want to make certain the message is delivered (resent) when lost, and if the order of a series of messages is relevant. E.g. game actions such as &quot;1. wield weapon, 2. attack, 3. dodge&quot;.</div>
</li>
<li><div> Choose unreliable and fast transport for messages if the next message makes any previously delayed or lost message obsolete and synchronizes the state again. E.g. a series of new locations while walking.</div>
</li>
</ul>
</div>
<h2><a>Important: Use Multi-Threading</a></h2>
<div>
<p>
You cannot modify the scenegraph in the NetworkThread. You have to create a Callable, enqueue the Callable in the OpenGLThread, and the callable makes the modification in the correct moment. A Callable is a Java class representing a (possibly time-intensive), self-contained task.
</p>
<pre>app.enqueue&#40;callable&#41;;</pre>
<p>
Learn more about <a href="/com/jme3/gde/core/docs/jme3/advanced/multithreading.html">multithreading</a> here.
</p>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:network?do=showtag&amp;tag=tag%3Anetwork">network</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:networking?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 24 KiB

@ -1,77 +1,263 @@
<h1><a
name="creating_user_interfaces_with_nifty_gui">Creating User Interfaces with Nifty GUI</a></h1><div
class="level1"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nifty-gui.png?id=jme3%3Aadvanced%3Anifty_gui"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png?w=310&amp;h=250" class="medialeft" align="left" alt="" width="310" height="250" /></a></p><p> Although it is possible to embed a <a
href="/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html">jME3 canvas</a> in a Swing <acronym
title="Graphical User Interface">GUI</acronym> app, a 3D game typically runs full-screen, or in a window of its own. This soon raises the question of how to add a user interface: Most games respond to the escape key by displaying buttons that allow users to switch to different screens – for example to view high scores, customize settings, or load saved games.</p><p> This doc introduces you to <a
href="http://nifty-gui.lessvoid.com/">Nifty GUI</a>, a Java library for graphical user interfaces (GUIs). Nifty <acronym
title="Graphical User Interface">GUI</acronym> (<code>de.lessvoid.nifty</code> package) is well integrated with jME3 via the <code>com.jme3.niftygui</code> package. You define the <acronym
title="Graphical User Interface">GUI</acronym> layout in <acronym
title="Extensible Markup Language">XML</acronym> and call it from your Java code. All the JAR libraries that you need are already included in your jME3 download, so you do not need to install anything extra (Just make sure they are on the classpath).</p><p> <em>Typically, you lay out the Nifty <acronym
title="Graphical User Interface">GUI</acronym> using <acronym
title="Extensible Markup Language">XML</acronym>, but using Java will soon be a second option.</em></p></div><h2><a
name="overview">Overview</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nifty-gui-example.png?id=jme3%3Aadvanced%3Anifty_gui"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-example.png?w=360&amp;h=203" class="mediaright" align="right" alt="" width="360" height="203" /></a></p><p> There are three steps needed to add a <acronym
title="Graphical User Interface">GUI</acronym> to your jME3 game:</p><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a></div></li><li
class="level1"><div
class="li"> Integrate the <acronym
title="Graphical User Interface">GUI</acronym> into the Game</div><ul><li
class="level2"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Overlay the User Interface Over the Screen</a>, or</div></li><li
class="level2"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Project the User Interface Onto a Texture</a></div></li></ul></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyGui.java">TestNiftyGui.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyToMesh.java">TestNiftyToMesh.java</a></div></li><li
class="level1"><div
class="li"> You can find more sample code in the nifty-examples-1.3-SNAPSHOT.jar file.</div></li></ul></div><h2><a
name="pro_tipuse_xml_schema">Pro Tip: Use XML Schema</a></h2><div
class="level2"><p> If you include the following <acronym
title="Extensible Markup Language">XML</acronym> schema in the first lines of your NiftyGUI <acronym
title="Extensible Markup Language">XML</acronym> files, your IDE will give you helpful hints and code completion.</p><pre><span>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span>&lt;nifty xmlns=&quot;http://nifty-gui.sourceforge.net/nifty.xsd&quot; </span>
<span> xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; </span>
<span> xsi:schemaLocation=&quot;http://nifty-gui.sourceforge.net/nifty.xsd
http://nifty-gui.sourceforge.net/nifty.xsd&quot;&gt;</span>
&nbsp;
&lt;!-- Example: The IDE will now tell you that one &lt;screen&gt;&lt;/screen&gt; element is expected here, etc. --&gt;
&nbsp;
<span><span>&lt;/nifty&gt;</span></span></pre></div><h2><a
name="nifty_documentation">Nifty Documentation</a></h2><div
class="level2"><p> Learn more from the NiftyGUI page!</p><ul><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Tutorials">Go Through the Nifty Tutorials</a></div></li><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Reference">Bookmark the Reference Guide</a></div></li><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Hello_World_Example">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Hello_World_Example</a></div></li><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction</a></div></li><li
class="level1"><div
class="li"> <a
href="http://jmonkeyengine.org/groups/gui/forum/topic/anyone-succeeded-in-changing-text-in-nifty-programatically/#post-109510">Changing the Text in Nifty GUIs programmatically</a></div></li></ul><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>, <a
href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Creating User Interfaces with Nifty GUI</a></h1>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-13.png">
</p>
<p>
You may want your players to press a button to save a game, you want a scrolling text field for highscores, a text label to display the score, drop-downs to select keymap preferences, or checkboxes to specify multi-media options. Usually you solve these tasks by using Swing controls. Although it is possible to embed a <a href="/com/jme3/gde/core/docs/jme3/advanced/swing_canvas.html">jME3 canvas</a> in a Swing <acronym title="Graphical User Interface">GUI</acronym>, a 3D game typically runs full-screen, or in a window of its own.
</p>
<p>
This document introduces you to <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.lessvoid.com/"><param name="text" value="<html><u>Nifty GUI</u></html>"><param name="textColor" value="blue"></object>, a Java library for building interactive graphical user interfaces (GUIs) for games or similar applications. Nifty <acronym title="Graphical User Interface">GUI</acronym> (the <code>de.lessvoid.nifty</code> package) is well integrated with jME3 through the <code>com.jme3.niftygui</code> package. You define the base <acronym title="Graphical User Interface">GUI</acronym> layout in <acronym title="Extensible Markup Language">XML</acronym>, and control it dynamically from your Java code. The necessary JAR libraries are included in your jME3 download, you do not need to install anything extra. (Just make sure they are on the classpath.)
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://vimeo.com/25637085"><param name="text" value="<html><u>Video demo of Nifty GUI 1.3</u></html>"><param name="textColor" value="blue"></object> </div>
</li>
</ul>
</div>
<h2><a>Overview</a></h2>
<div>
<p>
To add a Nifty <acronym title="Graphical User Interface">GUI</acronym> to your jME3 game:
</p>
<ol>
<li><div> <span><a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Understand the Nifty GUI Concepts</a></span> described on this page.</div>
</li>
<li><div> Lay out your graphical user interface:</div>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a> </div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Lay out the GUI in Java</a></div>
</li>
</ul>
</li>
<li><div> Integrate the <acronym title="Graphical User Interface">GUI</acronym> into the game:</div>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Overlay the User Interface Over the Screen</a> – or –</div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Project the User Interface Onto a Texture</a></div>
</li>
</ul>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ol>
</div>
<h2><a>Nifty GUI Concepts</a></h2>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-screen-layer-panel.png">
</p>
<p>
Nifty GUIs are made up of the following <strong>elements</strong>:
</p>
<ul>
<li><div> A Nifty <acronym title="Graphical User Interface">GUI</acronym> is made up of one or more <strong>screens</strong>.</div>
<ul>
<li><div> Nifty displays exactly one screen at a time.</div>
</li>
<li><div> Name the first screen <code>start</code>. Name any others whatever you like.</div>
</li>
<li><div> Every screen is <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">controlled by a Java Controller class</a>.</div>
</li>
</ul>
</li>
<li><div> A screen contains one or more <strong>layers</strong>.</div>
<ul>
<li><div> Layers are containers that impose an alignment on their content (vertical, horizontal, centered)</div>
</li>
<li><div> Layers overlap (z-order), and cannot be nested.</div>
</li>
</ul>
</li>
<li><div> A layer contains <strong>panels</strong>.</div>
<ul>
<li><div> Panels are containers that impose an alignment on their content (vertical, horizontal, centered)</div>
</li>
<li><div> Panels can be nested, and cannot overlap.</div>
</li>
</ul>
</li>
<li><div> A panel contains <strong>images, text, or controls (buttons, etc)</strong>.</div>
</li>
</ul>
<p>
General usage tips about elements:
</p>
<ul>
<li><div> You give an element an ID String if you want to interact with it. <br/>
You can also use transparent, ID-less panels as spacers.</div>
</li>
<li><div> For layers and panels, you specify width and height in percent, or use <code>*</code> to fill the remaining space automatically.</div>
</li>
<li><div> Screen, layers, and panels… </div>
<ul>
<li><div> can have an RGBA background color: You can use colors during layout development to highlight which container is which.</div>
</li>
<li><div> can be transparent: In the finished <acronym title="Graphical User Interface">GUI</acronym>, the visible elements are images, text, and controls inside the panels.</div>
</li>
</ul>
</li>
<li><div> The jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>&#039;s Nifty editor lets you switch between the <acronym title="Extensible Markup Language">XML</acronym> editor and a <acronym title="Graphical User Interface">GUI</acronym> preview, so you see the effects of your code changes.</div>
</li>
</ul>
</div>
<h2><a>Some Pro Tips...</a></h2>
<div>
</div>
<h4><a>XML or Java? Both!</a></h4>
<div>
<p>
The <acronym title="Extensible Markup Language">XML</acronym> and Java syntax are equivalent, so is it an either-or choice? Not quite.
We recommend to use <acronym title="Extensible Markup Language">XML</acronym> to lay out the static parts of the <acronym title="Graphical User Interface">GUI</acronym>. Then use Java syntax to control the dynamic parts of the <acronym title="Graphical User Interface">GUI</acronym> at runtime.
</p>
</div>
<h4><a>Activate Debug Highlighting</a></h4>
<div>
<p>
During development (and during this tutorial), the following debug code makes all panels visible. This helps you arrange them and find errors.
</p>
<pre>nifty.setDebugOptionPanelColors&#40;true&#41;;</pre>
<p>
Before the release, and for testing, set it to false again.
</p>
</div>
<h4><a>Use the jMonkeyEngine SDK</a></h4>
<div>
<p>
The <a href="/com/jme3/gde/core/docs/sdk.html">SDK</a> includes an <acronym title="Extensible Markup Language">XML</acronym> editor and previewer for Nifty <acronym title="Graphical User Interface">GUI</acronym> files. Open an <acronym title="Extensible Markup Language">XML</acronym> file, and switch between <acronym title="Extensible Markup Language">XML</acronym> and Preview mode.
</p>
</div>
<h4><a>Use XML Schema</a></h4>
<div>
<p>
Include the following <acronym title="Extensible Markup Language">XML</acronym> schema in the first line of your NiftyGUI <acronym title="Extensible Markup Language">XML</acronym> files and your IDE gives you hints and code completion.
</p>
<pre><span>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span>&lt;nifty xmlns=&quot;http://nifty-gui.sourceforge.net/nifty-1.3.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span>
<span> xsi:schemaLocation=&quot;http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd&quot;&gt;</span>
&lt;!-- Your IDE now tells you that one &lt;screen&gt;&lt;/screen&gt; element is expected here, etc. --&gt;
<span><span>&lt;/nifty&gt;</span></span></pre>
</div>
<h2><a>JME-Nifty Sample Code</a></h2>
<div>
<ul>
<li><div> <acronym title="Extensible Markup Language">XML</acronym> examples</div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test-data/Interface/Nifty/HelloJme.xml"><param name="text" value="<html><u>HelloJme.xml</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
<li><div> Java examples</div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyGui.java"><param name="text" value="<html><u>TestNiftyGui.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyToMesh.java"><param name="text" value="<html><u>TestNiftyToMesh.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
<li><div> jME3-ready version of the Nifty <acronym title="Graphical User Interface">GUI</acronym> 1.3 demo (sample code, Java)</div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://files.seapegasus.org/NiftyGuiDemo.zip"><param name="text" value="<html><u>NiftyGuiDemo.zip</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
<li><div> Find more sample code in the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-default-controls-examples/trunk/"><param name="text" value="<html><u>Nifty GUI source repository</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>External Documentation</a></h2>
<div>
<p>
Learn more from the NiftyGUI page!
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.sourceforge.net/webstart/nifty-tutorial-1.2.jnlp"><param name="text" value="<html><u>Interactive &quot;video&quot; tutorial (Webstart)</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty/apidocs/index.html"><param name="text" value="<html><u>Nifty 1.3 JavaDoc</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty-default-controls/apidocs/"><param name="text" value="<html><u>Nifty 1.3 Controls JavaDoc</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Nifty_Standard_Controls_%28Nifty_1.3%29"><param name="text" value="<html><u>Examples of Standard Controls in Nifty 1.3:</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp"><param name="text" value="<html><u>Nifty Syntax</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Tutorials"><param name="text" value="<html><u>The Nifty Tutorials</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Reference"><param name="text" value="<html><u>Bookmark the Reference Guide</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Hello_World_Example"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Hello_World_Example</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/gui/forum/topic/anyone-succeeded-in-changing-text-in-nifty-programatically/#post-109510"><param name="text" value="<html><u>Forum post: Changing Text in Nifty GUIs programmatically</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
Next, learn how to lay out your graphical user interface. Typically, you start with <acronym title="Extensible Markup Language">XML</acronym>.
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Lay out the GUI in XML</a> (recommended)</div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Lay out the GUI in Java</a> (optional)</div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui?do=export_xhtmlbody">view online version</a></em></p>

@ -1,136 +1,315 @@
<h1><a
name="interacting_with_the_gui_from_java">Interacting with the GUI from Java</a></h1><div
class="level1"><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div></li><li
class="level1"><div
class="li"> <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> Java Interaction</strong></div></li></ol><p> The main purpose of the <acronym
title="Graphical User Interface">GUI</acronym> is to send events back to your Java class that indicate what the users clicked, which settings they chose, which values they entered into a field, etc. In the Java class, you want to respond with an appropriate action, or store the entered settings in a file, etc.</p></div><h2><a
name="connect_gui_to_java_controller">Connect GUI to Java Controller</a></h2><div
class="level2"><p> How does the <acronym
title="Extensible Markup Language">XML</acronym> file send a message back to your Java application? You register a ScreenController (a Java class) to every NiftyGUI screen.
Create a ScreenController by creating a Java class that implements the <code>de.lessvoid.nifty.screen.ScreenController</code> interface and its abtract methods.</p><pre>package my.game;
<h1><a>Interacting with the GUI from Java</a></h1>
<div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI Concepts</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div> <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym> Java Interaction</strong></div>
</li>
</ol>
<p>
In the previous parts of the tutorial, you created a two-screen user interface. But it is still static, and when you click the buttons, nothing happens yet. The purpose of the <acronym title="Graphical User Interface">GUI</acronym> is to communicate with your Java classes: Your game needs to know what the users clicked, which settings they chose, which values they entered into a field, etc. Similarly, the user needs to know what the currently game state is (score, health, etc).
</p>
</div>
<h2><a>Connect GUI to Java Controller</a></h2>
<div>
<p>
To let a Nifty screen communicate with the Java application, you register a <code>ScreenController</code> to every NiftyGUI screen. You create a ScreenController by creating a Java class that implements the <code>de.lessvoid.nifty.screen.ScreenController</code> interface and its abtract methods.
</p>
<p>
<strong>Pro Tip:</strong> Since you are writing a jME3 application, you can additionally make the ScreenController class extend the <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">AbstractAppState</a> class! This gives the ScreenController access to the application object and to the update loop!
</p>
<pre>package tutorial;
&nbsp;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
public class MySettingsScreen implements ScreenController &#123;
public MySettingsScreen&#40;MyGameData data &#41;&#123; /** constructor */ &#125;
public void bind&#40;Nifty nifty, Screen screen&#41; &#123; &#125;
&nbsp;
public class MyStartScreen extends AbstractAppState implements ScreenController &#123;
&nbsp;
private Nifty nifty;
private Screen screen;
private SimpleApplication app;
&nbsp;
/** custom methods */
&nbsp;
public MyStartScreen&#40;String data&#41; &#123;
/** You custom constructor, can accept arguments */
&#125;
&nbsp;
/** Nifty GUI ScreenControl methods */
&nbsp;
public void bind&#40;Nifty nifty, Screen screen&#41; &#123;
this.nifty = nifty;
this.screen = screen;
&#125;
&nbsp;
public void onStartScreen&#40;&#41; &#123; &#125;
&nbsp;
public void onEndScreen&#40;&#41; &#123; &#125;
&#125;</pre><p> The name and package of your custom ScreenController class (here <code>my.game.MySettingsScreen</code>) goes into the controller parameter of the respective screen it belongs to:</p><pre><span><span>&lt;nifty&gt;</span></span>
<span>&lt;screen id=&quot;settings&quot; controller=&quot;my.game.MySettingsScreen&quot;&gt;</span>
&lt;!-- layer and panel code ... --&gt;
<span><span>&lt;/screen&gt;</span></span>
<span><span>&lt;/nifty&gt;</span></span></pre><p> Now the Java class <code>my.game.MySettingsScreen</code> and this <acronym
title="Graphical User Interface">GUI</acronym> screen (<code>settings</code>) are connected.</p></div><h2><a
name="make_gui_and_java_interact">Make GUI and Java Interact</a></h2><div
class="level2"><p> In most cases, you will want to pass game data in and out of the ScreenController. Note that you can pass any arguments into your ScreenController constructor. In the example above, the object with the necessary data is is <code>MyGameData data</code>.
You can use any of the three following approaches to make Java classes interact with the <acronym
title="Graphical User Interface">GUI</acronym>, and you can also combine them, depending on what you want to do.</p></div><h3><a
name="gui_calls_a_void_java_method">GUI Calls a Void Java Method</a></h3><div
class="level3"><p> To respond to an interaction, add the &lt;interact /&gt; element to a panel and specify the Java method you want to call. In this example, we want to call <code>sayHello()</code> when a panel on the screen is clicked.</p><pre>...
<span>&lt;panel id=&quot;panel&quot; height=&quot;25%&quot; width=&quot;35%&quot; align=&quot;center&quot; valign=&quot;center&quot;</span>
<span> backgroundColor=&quot;#f60f&quot; childLayout=&quot;center&quot; visibleToMouse=&quot;true&quot;&gt;</span>
<span>&lt;text id=&quot;text&quot; font=&quot;aurulent-sans-17.fnt&quot; color=&quot;#000f&quot;</span>
<span> text=&quot;Hello World!&quot; align=&quot;center&quot; valign=&quot;center&quot; /&gt;</span>
<span>&lt;interact onClick=&quot;sayHello(hi)&quot;/&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
...</pre><p> Back in this screen&#039;s Java class, we specify what the <code>sayHello()</code> method does. As you see, you can include String arguments in the call.</p><pre>public class MySettingsScreen implements ScreenController &#123;
...
public void sayHello&#40;String myarg&#41; &#123;
System.out.println&#40;&quot;Nifty says &quot;+myarg&#41;;
&nbsp;
/** jME3 AppState methods */
&nbsp;
@Override
public void initialize&#40;AppStateManager stateManager, Application app&#41; &#123;
super.initialize&#40;stateManager, app&#41;;
this.app=&#40;SimpleApplication&#41;app;
&#125;
&#125;</pre></div><h3><a
name="gui_gets_return_value_from_java_method">GUI Gets Return Value from Java Method</a></h3><div
class="level3"><p> You can send a message from Java to Nifty. In this example, the Java class <code>callThis()</code> in MySettingsScreen defines the Text that is displayed in the textfield after the words <code>Hello World, …!</code> First define a Java method in the screen controller, in this example, <code>callThis()</code>.</p><pre>public class MySettingsScreen implements ScreenController &#123;
...
public String callThis&#40;&#41; &#123;
return &quot;my friend&quot;;
&nbsp;
@Override
public void update&#40;float tpf&#41; &#123;
/** jME update loop! */
&#125;
&#125;</pre><p> Nifty uses <code>${CALL.callThis()}</code> to get the return value of a method from your ScreenController Java class.</p><pre>...
<span>&lt;panel id=&quot;panel&quot; height=&quot;25%&quot; width=&quot;35%&quot; align=&quot;center&quot; valign=&quot;center&quot;</span>
<span> backgroundColor=&quot;#f60f&quot; childLayout=&quot;center&quot; visibleToMouse=&quot;true&quot;&gt;</span>
<span>&lt;text id=&quot;text&quot; font=&quot;aurulent-sans-17.fnt&quot; color=&quot;#000f&quot;</span>
<span> text=&quot;Hello World, ${CALL.callThis()}!&quot; align=&quot;center&quot; valign=&quot;center&quot; /&gt;</span>
<span>&lt;interact onClick=&quot;sayHello(hi)&quot;/&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
...</pre><p> You can also use this for Strings and numeric values, e.g. when you read settings from a file, you read them like this.</p></div><h3><a
name="java_modifies_nifty_elements_and_events">Java Modifies Nifty Elements and Events</a></h3><div
class="level3"><p> You can also alter the appearance and functions of your nifty elements from Java.
Here&#039;s an example of how to change the image <code>myElement</code>:</p><pre>NiftyImage img = nifty.getRenderEngine&#40;&#41;.createImage&#40;&quot;Interface/Images/image.png&quot;, false&#41;;
Element niftyElement = nifty.getCurrentScreen&#40;&#41;.findElementByName&#40;&quot;myElement&quot;&#41;;
niftyElement.getRenderer&#40;ImageRenderer.class&#41;.setImage&#40;img&#41;;</pre><p> The same is valid for other elements, for example text fields:</p><pre>niftyElement.getRenderer&#40;TextRenderer.class&#41;.setText&#40;&quot;New text&quot;&#41;;</pre><p> Similarly, to change the onClick() event of an element, create an <code>ElementInteraction</code> object:</p><pre>Element niftyElement = nifty.getCurrentScreen&#40;&#41;.findElementByName&#40;&quot;myElement&quot;&#41;;
niftyElement.getElementInteraction&#40;&#41;.getPrimary&#40;&#41;.setOnMouseOver&#40;new NiftyMethodInvoker&#40;nifty, &quot;myCustomMethod()&quot;, this&#41;&#41;;</pre><p> For this to work, there already needs to be an &lt; interact &gt; tag inside your xml element:</p><pre>&lt;interact onClick=&quot;doNothing()&quot;/&gt;</pre></div><h2><a
name="concepts_examples">Concepts &amp; Examples</a></h2><div
class="level2"><p> note: Nifty-gui 1.3 oriented.<br/></p></div><h3><a
name="how_do_i_create_a_popup_menu_that_i_populate_in_java">How do I create a popup menu that I populate in Java?</a></h3><div
class="level3"><p> Even though you create and populate the popup menu in Java you still need a &quot;placeholder&quot; in your <acronym
title="Extensible Markup Language">XML</acronym> file, below is an example extract:</p><pre><span>&lt;useControls filename=&quot;nifty-default-controls.xml&quot;/&gt;</span>
...
<span>&lt;popup id=&quot;niftyPopupMenu&quot; childLayout=&quot;absolute-inside&quot;</span>
<span> controller=&quot;ControllerOfYourChoice&quot; width=&quot;10%&quot;&gt;</span>
<span>&lt;interact onClick=&quot;closePopup()&quot;</span>
<span> onSecondaryClick=&quot;closePopup()&quot; onTertiaryClick=&quot;closePopup()&quot; /&gt;</span>
<span>&lt;control id=&quot;#menu&quot; name=&quot;niftyMenu&quot; /&gt;</span>
<span><span>&lt;/popup&gt;</span></span>
...</pre><p> A brief explanation of some the attributes above:</p><ul><li
class="level1"><div
class="li"> the popup id will be used within your Java code so that nifty knows which popup placeholder to create</div></li><li
class="level1"><div
class="li"> controller will tell nifty which Java class handles MenuItemActivatedEvent</div></li><li
class="level1"><div
class="li"> on(Secondary/Tertiary)Click tells nifty to close the popup if the user clicks anywhere except on the menu items (in this example)</div></li><li
class="level1"><div
class="li"> control id will be used by the Java class to define a control type (i.e. Menu)</div></li></ul><p> Java code within your defined ScreenController implementation:<br/></p><pre>private Element popup;
&nbsp;
&#125;</pre>
<p>
The name and package of your custom ScreenController class (here <code>tutorial.MyStartScreen</code>) goes into the controller parameter of the respective <acronym title="Extensible Markup Language">XML</acronym> screen it belongs to. For example:
</p>
<pre><span><span>&lt;nifty&gt;</span></span>
<span>&lt;screen id=&quot;start&quot; controller=&quot;tutorial.MyStartScreen&quot;&gt;</span>
&lt;!-- layer and panel code ... --&gt;
<span><span>&lt;/screen&gt;</span></span>
<span><span>&lt;/nifty&gt;</span></span></pre>
<p>
Or the same in a Java syntax, respectively:
</p>
<pre> nifty.addScreen&#40;&quot;start&quot;, new ScreenBuilder&#40;&quot;start&quot;&#41; &#123;&#123;
controller&#40;new tutorial.MyStartScreen&#40;&#41;&#41;;</pre>
<p>
Now the Java class <code>MyStartScreen</code> and this <acronym title="Graphical User Interface">GUI</acronym> screen (<code>start</code>) are connected. For this example you can also connect the <code>hud</code> screen to MyStartScreen.
</p>
</div>
<h2><a>Make GUI and Java Interact</a></h2>
<div>
<p>
In most cases, you will want to pass game data in and out of the ScreenController. Note that you can pass any custom arguments from your Java class into your ScreenController constructor (<code>public MyStartScreen(GameData data) {}</code>).
</p>
<p>
Use any combination of the three following approaches to make Java classes interact with the <acronym title="Graphical User Interface">GUI</acronym>.
</p>
</div>
<h3><a>GUI Calls a Void Java Method</a></h3>
<div>
<p>
This is how you respond to an <acronym title="Graphical User Interface">GUI</acronym> interaction such as clicks in <acronym title="Extensible Markup Language">XML</acronym> GUIs:
</p>
<ol>
<li><div> Add <code>visibleToMouse=&quot;true&quot;</code> to the parent element!</div>
</li>
<li><div> Embed the <code>&lt;interact /&gt;</code> element into the parent element. </div>
</li>
<li><div> Specify the Java methods that you want to call when the users performs certain actions, such as clicking. <br/>
Example: <code>&lt;interact onClick=&quot;startGame(hud)&quot; /&gt;</code></div>
</li>
</ol>
<p>
Or this is how you respond to an <acronym title="Graphical User Interface">GUI</acronym> interaction such as clicks in Java GUIs:
</p>
<ol>
<li><div> Add <code>visibleToMouse(true);</code> to the parent element!</div>
</li>
<li><div> Embed one of the <code>interact…()</code> elements into the parent element</div>
</li>
<li><div> Specify the Java method that you want to call after the interaction. <br/>
Example: <code>interactOnClick(&quot;startGame(hud)&quot;);</code></div>
</li>
</ol>
<p>
In the following example, we call the <code>startGame()</code> method when the player clicks the Start button, and <code>quitGame()</code> when the player clicks the Quit button.
</p>
<pre> <span>&lt;panel id=&quot;panel_bottom_left&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;control name=&quot;button&quot; label=&quot;Start&quot; id=&quot;StartButton&quot; align=&quot;center&quot; valign=&quot;center&quot; </span>
<span> visibleToMouse=&quot;true&quot; &gt;</span>
<span>&lt;interact onClick=&quot;startGame(hud)&quot;/&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span>
&nbsp;
<span>&lt;panel id=&quot;panel_bottom_right&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;control name=&quot;button&quot; label=&quot;Quit&quot; id=&quot;QuitButton&quot; align=&quot;center&quot; valign=&quot;center&quot; </span>
<span> visibleToMouse=&quot;true&quot; &gt;</span>
<span>&lt;interact onClick=&quot;quitGame()&quot;/&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
Or the same in a Java syntax, respectively:
</p>
<pre>control&#40;new ButtonBuilder&#40;&quot;StartButton&quot;, &quot;Start&quot;&#41; &#123;&#123;
alignCenter&#40;&#41;;
valignCenter&#40;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
visibleToMouse&#40;true&#41;;
interactOnClick&#40;&quot;startGame(hud)&quot;&#41;;
&#125;&#125;&#41;;
...
public void createMyPopupMenu&#40;&#41;&#123;
popup = nifty.createPopup&#40;&quot;niftyPopupMenu&quot;&#41;;
Menu.class&#41;;
myMenu.setWidth&#40;new SizeValue&#40;&quot;100px&quot;&#41;&#41;; //must be set
myMenu.addMenuItem&#40;&quot;Click me!&quot;, &quot;menuItemIcon.png&quot;, new menuItem&#40;&quot;menuItemid&quot;, &quot;blah blah&quot;&#41;&#41;; //menuItem is a custom class
nifty.subscribe&#40;nifty.getCurrentScreen&#40;&#41;, myMenu.getId&#40;&#41;, MenuItemActivatedEvent.class, new MenuItemActivatedEventSubscriber&#40;&#41;&#41;;
&#125;
public void showMenu&#40;&#41;&#123; //the method to trigger the menu
createMyPopupMenu&#40;&#41; //you should call this in your constructor rather than here if it is a menu that is going to be used many times
nifty.showPopup&#40;nifty.getCurrentScreen&#40;&#41;, popup.getId&#40;&#41;, null&#41;; //call the popup to screen of your choice
&#125;
private class menuItem&#123;
public String id;
public String name;
public menuItem&#40;String name&#41;&#123;
this.id= id;
this.name = name;
&nbsp;
control&#40;new ButtonBuilder&#40;&quot;QuitButton&quot;, &quot;Quit&quot;&#41; &#123;&#123;
alignCenter&#40;&#41;;
valignCenter&#40;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
visibleToMouse&#40;true&#41;;
interactOnClick&#40;&quot;quitGame()&quot;&#41;;
&#125;&#125;&#41;;</pre>
<p>
Back in the MyStartScreen class, you specify what the <code>startGame()</code> and <code>quitGame()</code> methods do. As you see, you can pass String arguments (here <code>hud</code>) in the method call. You also see that you have access to the app object.
</p>
<pre>public class MyStartScreen implements ScreenController &#123;
...
&nbsp;
/** custom methods */
public void startGame&#40;String nextScreen&#41; &#123;
nifty.gotoScreen&#40;nextScreen&#41;; // switch to another screen
// start the game and do some more stuff...
&#125;
&#125;</pre><ul><li
class="level1"><div
class="li"> createMyPopupMenu() creates the menu with set width so that you can populate it</div></li><li
class="level1"><div
class="li"> showMenu() is called by something to trigger the menu (i.e. could be a Key or some other method)</div></li></ul><p> To handle menu item events (i.e. calling a method when you click on a menu item) you subscribe a EventTopicSubscriber&lt;MenuItemActivatedEvent&gt; class implementation to a nifty screen and element.<br/></p><pre>private class MenuItemActivatedEventSubscriber implements EventTopicSubscriber&lt;MenuItemActivatedEvent&gt; &#123;
@Override
public void onEvent&#40;final String id, final MenuItemActivatedEvent event&#41; &#123;
menuItem item = &#40;menuItem&#41; event.getItem&#40;&#41;;
if &#40;&quot;menuItemid&quot;.equals&#40;item.id&#41;&#41; &#123;
//do something !!!
&nbsp;
public void quitGame&#40;&#41; &#123;
app.stop&#40;&#41;;
&#125;
&nbsp;
...
&#125;</pre>
<p>
The startGame() example simply switches the <acronym title="Graphical User Interface">GUI</acronym> to the <code>hud</code> screen when the user clicks Start. Of course, in a real game, you would perform more steps here: Load the game level, switch to in-game input and navigation handling, set a custom <code>running</code> boolean to true, attach custom in-game AppStates – and lots more.
</p>
<p>
The quitGame() example shows that you have access to the application <code>app</code> object because you made the ScreenController extend AbstractAppState.
</p>
</div>
<h3><a>GUI Gets Return Value from Java Method</a></h3>
<div>
<p>
When the Nifty <acronym title="Graphical User Interface">GUI</acronym> is initialized, you can get data from Java. In this example, the Java class <code>getPlayerName()</code> in <code>MyStartScreen</code> defines the Text that is displayed in the textfield before the words <code>&#039;s Cool Game</code>.
</p>
<p>
First define a Java method in the screen controller, in this example, <code>getPlayerName()</code>.
</p>
<pre>public class MySettingsScreen implements ScreenController &#123;
...
public String getPlayerName&#40;&#41;&#123;
return System.getProperty&#40;&quot;user.name&quot;&#41;;
&#125;
&#125;;</pre></div><h2><a
name="useful_links">Useful Links</a></h2><div
class="level2"><p> Nifty 1.3 controls Java Docs: <a
href="http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty-default-controls/apidocs/">http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty-default-controls/apidocs/</a> <br/> <br/> Nifty 1.3 Java Docs: <a
href="http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty/apidocs/index.html">http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty/apidocs/index.html</a> <br/> <br/> Examples of standard controls in Nifty 1.3: <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Nifty_Standard_Controls_%28Nifty_1.3%29">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Nifty_Standard_Controls_%28Nifty_1.3%29</a> <br/> <br/> Learn more: <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp">Nifty Syntax</a></p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>, <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>, <a
href="/wiki/doku.php/tag:controller?do=showtag&amp;tag=tag%3Acontroller">controller</a>, <a
href="/wiki/doku.php/tag:controllers?do=showtag&amp;tag=tag%3Acontrollers">controllers</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_java_interaction?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
<p>
Nifty uses <code>${CALL.getPlayerName()}</code> to get the return value of the getPlayerName() method from your ScreenController Java class.
</p>
<pre><span>&lt;text text=&quot;${CALL.getPlayerName()}'s Cool Game&quot; font=&quot;Interface/Fonts/Default.fnt&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;</span></pre>
<p>
Or the same in a Java syntax, respectively:
</p>
<pre>text&#40;new TextBuilder&#40;&#41; &#123;&#123;
text&#40;&quot;${CALL.getPlayerName()}'s Cool Game&quot;&#41;;
font&#40;&quot;Interface/Fonts/Default.fnt&quot;&#41;;
height&#40;&quot;100%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;</pre>
<p>
You can use this for Strings and numeric values (e.g. when you read settings from a file, you display the results in the <acronym title="Graphical User Interface">GUI</acronym>) and also for methods with side effects.
</p>
</div>
<h3><a>Java Modifies Nifty Elements and Events</a></h3>
<div>
<p>
You can also alter the appearance and functions of your nifty elements from Java. Make certain that the element that you want to alter has its <code>id=&quot;name&quot;</code> attribute set, so you can identy and address it.
</p>
<p>
Here&#039;s an example of how to change an image called <code>playerhealth</code>:
</p>
<pre>// load or create new image
NiftyImage img = nifty.getRenderEngine&#40;&#41;.createImage&#40;&quot;Interface/Images/face2.png&quot;, false&#41;;
// find old image
Element niftyElement = nifty.getCurrentScreen&#40;&#41;.findElementByName&#40;&quot;playerhealth&quot;&#41;;
// swap old with new image
niftyElement.getRenderer&#40;ImageRenderer.class&#41;.setImage&#40;img&#41;;</pre>
<p>
The same is valid for other elements, for example a text label &quot;score&quot;:
</p>
<pre>// find old text
Element niftyElement = nifty.getCurrentScreen&#40;&#41;.findElementByName&#40;&quot;score&quot;&#41;;
// swap old with new text
niftyElement.getRenderer&#40;TextRenderer.class&#41;.setText&#40;&quot;124&quot;&#41;;</pre>
<p>
Similarly, to change the onClick() event of an element, create an <code>ElementInteraction</code> object:
</p>
<pre>Element niftyElement = nifty.getCurrentScreen&#40;&#41;.findElementByName&#40;&quot;myElement&quot;&#41;;
niftyElement.getElementInteraction&#40;&#41;.getPrimary&#40;&#41;.setOnMouseOver&#40;new NiftyMethodInvoker&#40;nifty, &quot;myCustomMethod()&quot;, this&#41;&#41;;</pre>
<p>
For this to work, there already needs to be a (possibly inactive) <code>&lt;interact /&gt;</code> tag inside your xml element:
</p>
<pre><span>&lt;interact onClick=&quot;doNothing()&quot;/&gt;</span></pre>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
You&#039;re done with the basic Nifty <acronym title="Graphical User Interface">GUI</acronym> for jME3 tutorial. You can proceed to advanced topics and learn how add controls and effects:
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_scenarios.html"> Nifty GUI Scenarios</a></div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>,
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>,
<a href="/wiki/doku.php/tag:controller?do=showtag&amp;tag=tag%3Acontroller">controller</a>,
<a href="/wiki/doku.php/tag:controllers?do=showtag&amp;tag=tag%3Acontrollers">controllers</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_java_interaction?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,633 @@
<h1><a>Laying Out the GUI in Java</a></h1>
<div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI Concepts</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym> Java Layout</strong></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ol>
<p>
<strong>Work in progress</strong> You can &quot;draw&quot; the <acronym title="Graphical User Interface">GUI</acronym> to the screen by writing Java code – alternatively to using <acronym title="Extensible Markup Language">XML</acronym>. Typically you lay out the static base <acronym title="Graphical User Interface">GUI</acronym> in <acronym title="Extensible Markup Language">XML</acronym>, and use Java commands if you need to change the <acronym title="Graphical User Interface">GUI</acronym> dynamically at runtime. In theory, you can also lay out the whole <acronym title="Graphical User Interface">GUI</acronym> in Java (but we don&#039;t cover that here).
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
Sample project
</p>
<ul>
<li><div> <strong>Original Source Code:</strong> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-default-controls-examples/trunk/src/main/java/de/lessvoid/nifty/examples/"><param name="text" value="<html><u>/nifty-default-controls-examples/trunk/src/main/java/de/lessvoid/nifty/examples/</u></html>"><param name="textColor" value="blue"></object>. <br/>
</div>
</li>
<li><div> <strong>Download demo project:</strong> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://files.seapegasus.org/NiftyGuiDemo.zip"><param name="text" value="<html><u>http://files.seapegasus.org/NiftyGuiDemo.zip</u></html>"><param name="textColor" value="blue"></object> (jme3-ready) <br/>
The full demo ZIP is based on <code>de.lessvoid.nifty.examples.controls.ControlsDemo.java</code>.</div>
<ol>
<li><div> The demo is a SimpleApplication-based game (use e.g. the BasicGame template in the jMonkeyPlatform).</div>
</li>
<li><div> Copy images and sound files into your project&#039;s <code>assets/Interface/</code> directory. (In this example, I copied them from <code>nifty-default-controls-examples/trunk/src/main/resources/</code> to <code>assets/Interface/</code>).</div>
</li>
<li><div> Make sure to use paths relative to your project&#039;s <code>assets/</code> directory.</div>
<ul>
<li><div> E.g. for .fnt/.png/.jpg files use <code>filename(&quot;Interface/yang.png&quot;);</code> ( not <code>filename(&quot;yang.png&quot;);</code>).</div>
</li>
<li><div> E.g. for .wav/.ogg files use <code>filename(&quot;Interface/sounds/gong.wav&quot;);</code> (not <code>filename(&quot;sounds/gong.wav&quot;);</code>).</div>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<p>
Just so you get a quick picture what Nifty <acronym title="Graphical User Interface">GUI</acronym>&#039;s Java Syntax looks like, here is the most basic example. It creates a screen with a layer and a panel that contains a button.
</p>
<pre>package mygame;
&nbsp;
import com.jme3.app.SimpleApplication;
import com.jme3.niftygui.NiftyJmeDisplay;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.PanelBuilder;
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
import de.lessvoid.nifty.screen.DefaultScreenController;
&nbsp;
<span>/**
* @author iamcreasy
*/</span>
public class Main extends SimpleApplication &#123;
&nbsp;
public static void main&#40;String&#91;&#93; args&#41; &#123;
Main app = new Main&#40;&#41;;
app.start&#40;&#41;;
&#125;
&nbsp;
@Override
public void simpleInitApp&#40;&#41; &#123;
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay&#40;
assetManager, inputManager, audioRenderer, guiViewPort&#41;;
Nifty nifty = niftyDisplay.getNifty&#40;&#41;;
guiViewPort.addProcessor&#40;niftyDisplay&#41;;
flyCam.setDragToRotate&#40;true&#41;;
&nbsp;
nifty.loadStyleFile&#40;&quot;nifty-default-styles.xml&quot;&#41;;
nifty.loadControlFile&#40;&quot;nifty-default-controls.xml&quot;&#41;;
&nbsp;
// &lt;screen&gt;
nifty.addScreen&#40;&quot;Screen_ID&quot;, new ScreenBuilder&#40;&quot;Hello Nifty Screen&quot;&#41;&#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;; // Screen properties
&nbsp;
// &lt;layer&gt;
layer&#40;new LayerBuilder&#40;&quot;Layer_ID&quot;&#41; &#123;&#123;
childLayoutVertical&#40;&#41;; // layer properties, add more...
&nbsp;
// &lt;panel&gt;
panel&#40;new PanelBuilder&#40;&quot;Panel_ID&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;; // panel properties, add more...
&nbsp;
// GUI elements
control&#40;new ButtonBuilder&#40;&quot;Button_ID&quot;, &quot;Hello Nifty&quot;&#41;&#123;&#123;
alignCenter&#40;&#41;;
valignCenter&#40;&#41;;
height&#40;&quot;5%&quot;&#41;;
width&#40;&quot;15%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
//.. add more GUI elements here
&nbsp;
&#125;&#125;&#41;;
// &lt;/panel&gt;
&#125;&#125;&#41;;
// &lt;/layer&gt;
&#125;&#125;.build&#40;nifty&#41;&#41;;
// &lt;/screen&gt;
&nbsp;
nifty.gotoScreen&#40;&quot;Screen_ID&quot;&#41;; // start the screen
&#125;
&#125;</pre>
</div>
<h2><a>Implement Your GUI Layout</a></h2>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/gui-layout-draft.png">
</p>
<p>
In this tutorial, you recreate the same screen as in the Nifty <acronym title="Graphical User Interface">GUI</acronym> <acronym title="Extensible Markup Language">XML</acronym> example.
</p>
<p>
Create an Screen.Java file in the <code>assets/Interfaces/</code> directory of your project. One Java file can contain several, or even all screens. As a reminder: Nifty displays one screen at a time; a screen contains several layers on top of one another; each layer contains panels that are embedded into another; the panels contain the actual content (text, images, or controls).
</p>
</div>
<h3><a>Make Screens</a></h3>
<div>
<p>
The following minimal Java file contains a start screen and a HUD screen. (Neither has been defined yet.)
</p>
<pre>nifty.addScreen&#40;&quot;start&quot;, new ScreenBuilder&#40;&quot;start&quot;&#41;&#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
// &lt;!-- ... --&gt;
&#125;&#125;.build&#40;nifty&#41;&#41;;
&nbsp;
nifty.addScreen&#40;&quot;hud&quot;, new ScreenBuilder&#40;&quot;hud&quot;&#41;&#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
// &lt;!-- ... --&gt;
&#125;&#125;.build&#40;nifty&#41;&#41;;</pre>
<p>
Every Nifty <acronym title="Graphical User Interface">GUI</acronym> must have a start screen. The others (in this example, the HUD screen) are optional.
</p>
</div>
<h3><a>Make Layers</a></h3>
<div>
<p>
The following Java code shows how we add layers to the start screen and HUD screen:
</p>
<pre>nifty.addScreen&#40;&quot;start&quot;, new ScreenBuilder&#40;&quot;start&quot;&#41;&#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
&nbsp;
// layer added
layer&#40;new LayerBuilder&#40;&quot;background&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#000f&quot;&#41;;
&nbsp;
// &lt;!-- ... --&gt;
&#125;&#125;&#41;;
&nbsp;
layer&#40;new LayerBuilder&#40;&quot;foreground&quot;&#41; &#123;&#123;
childLayoutVertical&#40;&#41;;
backgroundColor&#40;&quot;#0000&quot;&#41;;
&nbsp;
// &lt;!-- ... --&gt;
&#125;&#125;&#41;;
// layer added
&nbsp;
&#125;&#125;.build&#40;nifty&#41;&#41;;</pre>
<p>
Repeat the same, but use
</p>
<pre>nifty.addScreen(&quot;hud&quot;, new ScreenBuilder(&quot;hud&quot;){{</pre>
<p>
for the HUD screen.
</p>
<p>
In a layer, you can now add panels and arrange them. Panels are containers that mark the areas where you want to display text, images, or controls (buttons etc) later.
</p>
</div>
<h3><a>Make Panels</a></h3>
<div>
<p>
A panel is the inner-most container (that will contain the actual content: text, images, or controls). You place panels inside layers. The following panels go into in the <code>start</code> screen:
</p>
<pre> nifty.addScreen&#40;&quot;start&quot;, new ScreenBuilder&#40;&quot;start&quot;&#41; &#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
layer&#40;new LayerBuilder&#40;&quot;background&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#000f&quot;&#41;;
// &lt;!-- ... --&gt;
&#125;&#125;&#41;;
&nbsp;
layer&#40;new LayerBuilder&#40;&quot;foreground&quot;&#41; &#123;&#123;
childLayoutVertical&#40;&#41;;
backgroundColor&#40;&quot;#0000&quot;&#41;;
&nbsp;
// panel added
panel&#40;new PanelBuilder&#40;&quot;panel_top&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
alignCenter&#40;&#41;;
backgroundColor&#40;&quot;#f008&quot;&#41;;
height&#40;&quot;25%&quot;&#41;;
width&#40;&quot;75%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_mid&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
alignCenter&#40;&#41;;
backgroundColor&#40;&quot;#0f08&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;75%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_bottom&quot;&#41; &#123;&#123;
childLayoutHorizontal&#40;&#41;;
alignCenter&#40;&#41;;
backgroundColor&#40;&quot;#00f8&quot;&#41;;
height&#40;&quot;25%&quot;&#41;;
width&#40;&quot;75%&quot;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_bottom_left&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
valignCenter&#40;&#41;;
backgroundColor&#40;&quot;#44f8&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_bottom_right&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
valignCenter&#40;&#41;;
backgroundColor&#40;&quot;#88f8&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&#125;&#125;&#41;;
&#125;&#125;&#41;; // panel added
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;.build&#40;nifty&#41;&#41;;</pre>
<p>
The following panels go into in the <code>hud</code> screen:
</p>
<pre> nifty.addScreen&#40;&quot;hud&quot;, new ScreenBuilder&#40;&quot;hud&quot;&#41; &#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
&nbsp;
layer&#40;new LayerBuilder&#40;&quot;background&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#000f&quot;&#41;;
// &lt;!-- ... --&gt;
&#125;&#125;&#41;;
&nbsp;
layer&#40;new LayerBuilder&#40;&quot;foreground&quot;&#41; &#123;&#123;
childLayoutHorizontal&#40;&#41;;
backgroundColor&#40;&quot;#0000&quot;&#41;;
&nbsp;
// panel added
panel&#40;new PanelBuilder&#40;&quot;panel_left&quot;&#41; &#123;&#123;
childLayoutVertical&#40;&#41;;
backgroundColor&#40;&quot;#0f08&quot;&#41;;
height&#40;&quot;100%&quot;&#41;;
width&#40;&quot;80%&quot;&#41;;
// &lt;!-- spacer --&gt;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_right&quot;&#41; &#123;&#123;
childLayoutVertical&#40;&#41;;
backgroundColor&#40;&quot;#00f8&quot;&#41;;
height&#40;&quot;100%&quot;&#41;;
width&#40;&quot;20%&quot;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_top_right1&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#00f8&quot;&#41;;
height&#40;&quot;15%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_top_right2&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#44f8&quot;&#41;;
height&#40;&quot;15%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_bot_right&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
valignCenter&#40;&#41;;
backgroundColor&#40;&quot;#88f8&quot;&#41;;
height&#40;&quot;70%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;
&#125;&#125;&#41;; // panel added
&#125;&#125;&#41;;
&#125;&#125;.build&#40;nifty&#41;&#41;;</pre>
<p>
Try the sample. Remember to activate a screen using <code>nifty.gotoScreen(&quot;start&quot;);</code> or <code>hud</code> respectively.
The result should look as follows:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-panels.png">
</p>
</div>
<h2><a>Adding Content to Panels</a></h2>
<div>
<p>
See also <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><param name="text" value="<html><u>Layout Introduction</u></html>"><param name="textColor" value="blue"></object> on the Nifty <acronym title="Graphical User Interface">GUI</acronym> site.
</p>
</div>
<h3><a>Add Images</a></h3>
<div>
<p>
The start-background.png image is a fullscreen background picture. In the <code>start</code> screen, add the following image element:
</p>
<pre> nifty.addScreen&#40;&quot;start&quot;, new ScreenBuilder&#40;&quot;start&quot;&#41; &#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
layer&#40;new LayerBuilder&#40;&quot;background&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#000f&quot;&#41;;
&nbsp;
// add image
image&#40;new ImageBuilder&#40;&#41; &#123;&#123;
filename&#40;&quot;Interface/tutorial/start-background.png&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
The hud-frame.png image is a transparent frame that we use as HUD decoration. In the <code>hud</code> screen, add the following image element:
</p>
<pre> nifty.addScreen&#40;&quot;hud&quot;, new ScreenBuilder&#40;&quot;hud&quot;&#41; &#123;&#123;
controller&#40;new DefaultScreenController&#40;&#41;&#41;;
&nbsp;
layer&#40;new LayerBuilder&#40;&quot;background&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#000f&quot;&#41;;
&nbsp;
// add image
image&#40;new ImageBuilder&#40;&#41; &#123;&#123;
filename&#40;&quot;Interface/tutorial/hud-frame.png&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
The face1.png image is an image that you want to use as a status icon.
In the <code>hud</code> screen&#039;s <code>foreground</code> layer, add the following image element:
</p>
<pre> panel&#40;new PanelBuilder&#40;&quot;panel_top_right2&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#44f8&quot;&#41;;
height&#40;&quot;15%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&nbsp;
// add image
image&#40;new ImageBuilder&#40;&#41; &#123;&#123;
filename&#40;&quot;Interface/tutorial/face1.png&quot;&#41;;
valignCenter&#40;&#41;;
alignCenter&#40;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;30%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
This image is scaled to use 50% of the height and 30% of the width of its container.
</p>
</div>
<h3><a>Add Static Text</a></h3>
<div>
<p>
The game title is a typical example of static text. In the <code>start</code> screen, add the following text element:
</p>
<pre> // panel added
panel&#40;new PanelBuilder&#40;&quot;panel_top&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
alignCenter&#40;&#41;;
backgroundColor&#40;&quot;#f008&quot;&#41;;
height&#40;&quot;25%&quot;&#41;;
width&#40;&quot;75%&quot;&#41;;
&nbsp;
// add text
text&#40;new TextBuilder&#40;&#41; &#123;&#123;
text&#40;&quot;My Cool Game&quot;&#41;;
font&#40;&quot;Interface/Fonts/Default.fnt&quot;&#41;;
height&#40;&quot;100%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
For longer pieces of static text, such as an introduction, you can use wrap=&quot;true&quot;. Add the following text element to the <code>Start screen</code>:
</p>
<pre> panel&#40;new PanelBuilder&#40;&quot;panel_mid&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
alignCenter&#40;&#41;;
backgroundColor&#40;&quot;#0f08&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;75%&quot;&#41;;
// add text
text&#40;new TextBuilder&#40;&#41; &#123;&#123;
text&#40;&quot;Here goes some text describing the game and the rules and stuff. &quot;+
&quot;Incidentally, the text is quite long and needs to wrap at the end of lines. &quot;&#41;;
font&#40;&quot;Interface/Fonts/Default.fnt&quot;&#41;;
wrap&#40;true&#41;;
height&#40;&quot;100%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
The font used is jME3&#039;s default font &quot;Interface/Fonts/Default.fnt&quot; which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface</code> directory.
</p>
</div>
<h3><a>Add Controls</a></h3>
<div>
<p>
Before you can use any control, you must load a Control Definition first. Add the following two lines <em>before</em> your screen definitions:
</p>
<pre> nifty.loadStyleFile&#40;&quot;nifty-default-styles.xml&quot;&#41;;
nifty.loadControlFile&#40;&quot;nifty-default-controls.xml&quot;&#41;;</pre>
</div>
<h4><a>Label Control</a></h4>
<div>
<p>
Use label controls for text that you want to edit dynamically from Java. One example for this is the score display.
In the <code>hud</code> screen&#039;s <code>foreground</code> layer, add the following text element:
</p>
<pre> panel&#40;new PanelBuilder&#40;&quot;panel_top_right1&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
backgroundColor&#40;&quot;#00f8&quot;&#41;;
height&#40;&quot;15%&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
&nbsp;
control&#40;new LabelBuilder&#40;&#41;&#123;&#123;
color&#40;&quot;#000&quot;&#41;;
text&#40;&quot;123&quot;&#41;;
width&#40;&quot;100%&quot;&#41;;
height&#40;&quot;100%&quot;&#41;;
&#125;&#125;&#41;;</pre>
<p>
Note that the width and height do not scale the bitmap font, but the make indirectly certain it is centered. If you want a different size for the font, you need to provide an extra bitmap font (they come with fixes sizes and don&#039;t scale well).
</p>
</div>
<h4><a>Button Control</a></h4>
<div>
<p>
Our <acronym title="Graphical User Interface">GUI</acronym> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code>&lt;control&gt;</code> element:
</p>
<pre> panel&#40;new PanelBuilder&#40;&quot;panel_bottom_left&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
valignCenter&#40;&#41;;
backgroundColor&#40;&quot;#44f8&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&nbsp;
// add control
control&#40;new ButtonBuilder&#40;&quot;StartButton&quot;, &quot;Start&quot;&#41; &#123;&#123;
alignCenter&#40;&#41;;
valignCenter&#40;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;
&nbsp;
panel&#40;new PanelBuilder&#40;&quot;panel_bottom_right&quot;&#41; &#123;&#123;
childLayoutCenter&#40;&#41;;
valignCenter&#40;&#41;;
backgroundColor&#40;&quot;#88f8&quot;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&nbsp;
// add control
control&#40;new ButtonBuilder&#40;&quot;QuitButton&quot;, &quot;Quit&quot;&#41; &#123;&#123;
alignCenter&#40;&#41;;
valignCenter&#40;&#41;;
height&#40;&quot;50%&quot;&#41;;
width&#40;&quot;50%&quot;&#41;;
&#125;&#125;&#41;;
&nbsp;
&#125;&#125;&#41;;</pre>
<p>
Note that these controls don&#039;t do anything yet – we&#039;ll get to that soon.
</p>
</div>
<h4><a>Other Controls</a></h4>
<div>
<p>
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, … See also <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><param name="text" value="<html><u>Elements</u></html>"><param name="textColor" value="blue"></object> on the Nifty <acronym title="Graphical User Interface">GUI</acronym> site.
</p>
</div>
<h2><a>Intermediate Result</a></h2>
<div>
<p>
When you preview this code in the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
</p>
<p>
<strong>Tip:</strong> Remove all lines that set background colors, you only needed them to see the arrangement.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-simple-demo.png">
</p>
</div>
<h2><a>Nifty Java Settings</a></h2>
<div>
<p>
Before initializing the nifty screens, you set up properties and register media.
</p>
<div><table>
<tr>
<th> Nifty Method </th><th> Description </th>
</tr>
<tr>
<td> registerSound(&quot;mysound&quot;, &quot;Interface/abc.wav&quot;); </td><td> </td>
</tr>
<tr>
<td> registerMusic(&quot;mymusic&quot;, &quot;Interface/xyz.ogg&quot;); </td><td> </td>
</tr>
<tr>
<td> registerMouseCursor(&quot;mypointer&quot;, &quot;Interface/abc.png&quot;, 5, 4); </td><td> </td>
</tr>
<tr>
<td> registerEffect(?); </td><td> ? </td>
</tr>
<tr>
<td> setDebugOptionPanelColors(true);</td><td> Highlight all panels, makes it easier to arrange them. </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [17259-17582] -->
<p>
Example:
</p>
<pre>nifty.registerMouseCursor&#40;&quot;hand&quot;, &quot;Interface/mouse-cursor-hand.png&quot;, 5, 4&#41;;</pre>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
Integrate the <acronym title="Graphical User Interface">GUI</acronym> into the game. Typically, you will overlay the <acronym title="Graphical User Interface">GUI</acronym>.
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> (recommended)</div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a> (optional)</div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_java_layout?do=export_xhtmlbody">view online version</a></em></p>

@ -1,54 +1,87 @@
<h1><a
name="integrating_nifty_guioverlay">Integrating Nifty GUI: Overlay</a></h1><div
class="level1"><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a></div></li><li
class="level1"><div
class="li"> <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> Overlay</strong> or <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><p> Define a key (for example escape) that switches the <acronym
title="Graphical User Interface">GUI</acronym> on and off.
You can either overlay the running game with the <acronym
title="Graphical User Interface">GUI</acronym> (you will most likely pause the game then), or even <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">project</a> it as a texture onto a mesh texture (but then you cannot click to select).
On this page, we look at the overlay variant (more commonly used).</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nifty-gui-example.png?id=jme3%3Aadvanced%3Anifty_gui_overlay"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-example.png?w=360&amp;h=203" class="mediacenter" alt="" width="360" height="203" /></a></p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyGui.java">TestNiftyGui.java</a></div></li></ul></div><h2><a
name="overlaying_the_user_interface_over_the_screen">Overlaying the User Interface Over the Screen</a></h2><div
class="level2"><p> This code shows you how to overlay anything on the screen with the <acronym
title="Graphical User Interface">GUI</acronym>. This is the most common usecase.</p><pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay&#40;
<h1><a>Integrating Nifty GUI: Overlay</a></h1>
<div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI Concepts</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div> <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym> Overlay</strong> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ol>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-example.png">
</p>
<p>
Typically, you define a key (for example escape) that switches the <acronym title="Graphical User Interface">GUI</acronym> on and off. The <acronym title="Graphical User Interface">GUI</acronym> can be a StartScreen, OptionsScreen, CharacterCreationScreen, etc. While the <acronym title="Graphical User Interface">GUI</acronym> is up, you pause the running game, and then overlay the <acronym title="Graphical User Interface">GUI</acronym>. You also must switch to a different set of user inputs while the game is paused, so the player can use the mouse pointer and keyboard to interact with the <acronym title="Graphical User Interface">GUI</acronym>.
</p>
<p>
You can also <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">project</a> the <acronym title="Graphical User Interface">GUI</acronym> as a texture onto a mesh texture (but then you cannot click to select).
On this page, we look at the overlay variant, which is more commonly used in games.
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyGui.java"><param name="text" value="<html><u>TestNiftyGui.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Overlaying the User Interface Over the Screen</a></h2>
<div>
<p>
This code shows you how to overlay anything on the screen with the <acronym title="Graphical User Interface">GUI</acronym>. This is the most common usecase.
</p>
<pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay&#40;
assetManager, inputManager, audioRenderer, guiViewPort&#41;;
/** Create a new NiftyGUI object */
Nifty nifty = niftyDisplay.getNifty&#40;&#41;;
/** Read your XML and initialize your custom ScreenController */
nifty.fromXml&#40;&quot;Interface/helloworld.xml&quot;, &quot;start&quot;, new MySettingsScreen&#40;data&#41;&#41;;
nifty.fromXml&#40;&quot;Interface/tutorial/step2/screen.xml&quot;, &quot;start&quot;&#41;;
// nifty.fromXml(&quot;Interface/helloworld.xml&quot;, &quot;start&quot;, new MySettingsScreen(data));
// attach the Nifty display to the gui view port as a processor
guiViewPort.addProcessor&#40;niftyDisplay&#41;;
// disable the fly cam
flyCam.setDragToRotate&#40;true&#41;;</pre><p> The <code>MySettingsScreen</code> class is a custom de.lessvoid.nifty.screen.ScreenController in which you implement your <acronym
title="Graphical User Interface">GUI</acronym> behaviour. The variable <code>data</code> contains an object that you use to exchange state info with the game. See <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Nifty GUI Java Interaction</a> for details on how we created this class.</p><hr
/><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a></div></li><li
class="level1"><div
class="li"> <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> Overlay</strong> or <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_overlay?do=export_xhtmlbody">view online version</a></em></p>
flyCam.setDragToRotate&#40;true&#41;;</pre>
<p>
Currently you do not have a ScreenController – we will create one in the next exercise. As soon as you have a screen controller, you will use the commented variant of the <acronym title="Extensible Markup Language">XML</acronym> loading method:
</p>
<pre>nifty.fromXml&#40;&quot;Interface/helloworld.xml&quot;, &quot;start&quot;, new MySettingsScreen&#40;&#41;&#41;;</pre>
<p>
The <code>MySettingsScreen</code> class is a custom de.lessvoid.nifty.screen.ScreenController in which you will implement your <acronym title="Graphical User Interface">GUI</acronym> behaviour.
</p>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
Now that you have layed out and integrated the <acronym title="Graphical User Interface">GUI</acronym> in your app, you want to respond to user input and display the current game. Time to create a ScreenController!
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_overlay?do=export_xhtmlbody">view online version</a></em></p>

@ -1,30 +1,53 @@
<h1><a
name="integrating_nifty_guiprojection">Integrating Nifty GUI: Projection</a></h1><div
class="level1"><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> Projection</strong></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><p> Define a key (for example escape) that switches the <acronym
title="Graphical User Interface">GUI</acronym> on and off. You can either <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">overlay</a> the running game with the <acronym
title="Graphical User Interface">GUI</acronym> (you will most likely pause the game then), or even project it as a texture onto a mesh textures (but then you cannot click to select).
On this page, we look at the projection variant (less commonly used). <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nifty-gui.png?id=jme3%3Aadvanced%3Anifty_gui_projection"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png?w=310&amp;h=250" class="mediacenter" alt="" width="310" height="250" /></a></p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyToMesh.java">TestNiftyToMesh.java</a></div></li></ul></div><h2><a
name="projecting_the_user_interface_onto_a_texture">Projecting the User Interface Onto a Texture</a></h2><div
class="level2"><p> You can project the Nifty <acronym
title="Graphical User Interface">GUI</acronym> onto a texture, load the texture into a material, and assign it to a 3D mesh. Allthough this is possible the approach is rarely used since it is difficult to record clicks this way, you can only interact with this UI by keyboard or programmatically. (E.g. an action performed by a character standing in front of a &quot;computer&quot;)</p><pre>/** Create a new viewport for the GUI */
<h1><a>Integrating Nifty GUI: Projection</a></h1>
<div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI Concepts</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym> Projection</strong></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ol>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui.png">
</p>
<p>
Typically you define a key (for example escape) to switch the <acronym title="Graphical User Interface">GUI</acronym> on and off. Then you <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">overlay</a> the running game with the <acronym title="Graphical User Interface">GUI</acronym> (you will most likely pause the game then).
</p>
<p>
Alternatively, you can also project the <acronym title="Graphical User Interface">GUI</acronym> as a texture onto a mesh textures inside the game. Allthough this looks cool and &quot;immersive&quot;, this approach is rarely used since it is difficult to record clicks this way. You can only interact with this projected <acronym title="Graphical User Interface">GUI</acronym> by keyboard, or programmatically. You can select input fields using the arrow keys, and trigger actions using the return key.
</p>
<p>
This <acronym title="Graphical User Interface">GUI</acronym> projection variant is less commonly used than the <acronym title="Graphical User Interface">GUI</acronym> overlay variant. Usecases for <acronym title="Graphical User Interface">GUI</acronym> projection are, for example, a player avatar using an in-game computer screen.
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/niftygui/TestNiftyToMesh.java"><param name="text" value="<html><u>TestNiftyToMesh.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Projecting the User Interface Onto a Texture</a></h2>
<div>
<p>
You can project the Nifty <acronym title="Graphical User Interface">GUI</acronym> onto a texture, load the texture into a material, and assign it to a Geometry (Quads or Boxes are best).
</p>
<pre>/** Create a special viewport for the Nifty GUI */
ViewPort niftyView = renderManager.createPreView&#40;&quot;NiftyView&quot;, new Camera&#40;1024, 768&#41;&#41;;
niftyView.setClearEnabled&#40;true&#41;;
/** Create a new NiftyJmeDisplay for the integration */
@ -34,7 +57,8 @@ NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay&#40;
Nifty nifty = niftyDisplay.getNifty&#40;&#41;;
/** Read your XML and initialize your custom ScreenController */
nifty.fromXml&#40;&quot;Interface/helloworld.xml&quot;, &quot;start&quot;, new MySettingsScreen&#40;data&#41;&#41;;
/** We prepare a framebuffer for the texture niftytex */
&nbsp;
/** Prepare a framebuffer for the texture niftytex */
niftyView.addProcessor&#40;niftyDisplay&#41;;
FrameBuffer fb = new FrameBuffer&#40;1024, 768, 0&#41;;
fb.setDepthBuffer&#40;Format.Depth&#41;;
@ -42,32 +66,41 @@ Texture2D niftytex = new Texture2D&#40;1024, 768, Format.RGB8&#41;;
fb.setColorTexture&#40;niftytex&#41;;
niftyView.setClearEnabled&#40;true&#41;;
niftyView.setOutputFrameBuffer&#40;fb&#41;;
&nbsp;
/** This is the 3D cube we project the GUI on */
Box&#40;Vector3f.ZERO, 1, 1, 1&#41;;
Geometry geom = new Geometry&#40;&quot;Box&quot;, b&#41;;
Material mat = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Unshaded.j3md&quot;&#41;;
mat.setTexture&#40;&quot;m_ColorMap&quot;, niftytex&#41;; /** Here comes the texture! */
geom.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;geom&#41;;</pre><p> The MySettingsScreen class is a custom de.lessvoid.nifty.screen.ScreenController in which you implement your <acronym
title="Graphical User Interface">GUI</acronym> behaviour. The variable <code>data</code> contains an object that you use to exchange state info with the game. See <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Nifty GUI Java Interaction</a> for details on how we created this class.
Run the code sample. You select buttons on this <acronym
title="Graphical User Interface">GUI</acronym> with the arrow keys and then press return. Note that clicking on the texture will not work!
Again, check the <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Main_Page">Nifty GUI wiki</a> to get all the &quot;bells and whistles&quot; of the syntax!</p><hr
/><ol><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_xml_layout.html">Nifty GUI XML Layout</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> Projection</strong></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>, <a
href="/wiki/doku.php/tag:texture?do=showtag&amp;tag=tag%3Atexture">texture</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_projection?do=export_xhtmlbody">view online version</a></em></p>
rootNode.attachChild&#40;geom&#41;;</pre>
<p>
The MySettingsScreen class is a custom de.lessvoid.nifty.screen.ScreenController in which you implement your <acronym title="Graphical User Interface">GUI</acronym> behaviour. The variable <code>data</code> contains an object that you use to exchange state info with the game. See <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Nifty GUI Java Interaction</a> for details on how to create this class.
</p>
<p>
Run the code sample. You select buttons on this <acronym title="Graphical User Interface">GUI</acronym> with the arrow keys and then press return. Note that clicking on the texture will not work!
</p>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
Now that you have layed out and integrated the <acronym title="Graphical User Interface">GUI</acronym> in your app, you want to respond to user input and display the current game.
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>,
<a href="/wiki/doku.php/tag:texture?do=showtag&amp;tag=tag%3Atexture">texture</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_projection?do=export_xhtmlbody">view online version</a></em></p>

@ -1,121 +1,379 @@
<h1><a
name="laying_out_the_gui_in_xml">Laying out the GUI in XML</a></h1><div
class="level1"><ol><li
class="level1"><div
class="li"> <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> <acronym
title="Extensible Markup Language">XML</acronym> Layout</strong></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:nifty-screen-layer-panel.png?id=jme3%3Aadvanced%3Anifty_gui_xml_layout"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-screen-layer-panel.png" class="media" alt="" /></a></p><p> You &quot;draw&quot; the <acronym
title="Graphical User Interface">GUI</acronym> to the screen by writing <acronym
title="Extensible Markup Language">XML</acronym> code. We will be referring to the following elements:</p><ul><li
class="level1"><div
class="li"> Every Nifty Gui is made up of screens.</div><ul><li
class="level2"><div
class="li"> Nifty can display only one screen at a time.</div></li><li
class="level2"><div
class="li"> You must name the first screen <code>id=&quot;start&quot;</code>. Name any others whatever you like.</div></li><li
class="level2"><div
class="li"> Every screen is <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">controlled by a Java class</a>.</div></li></ul></li><li
class="level1"><div
class="li"> A screen contains one or more layers.</div><ul><li
class="level2"><div
class="li"> Layers are containers that impose an alignment on their content (vertical, horizontal, centered)</div></li><li
class="level2"><div
class="li"> Layers can overlap (z-order), but cannot be nested.</div></li><li
class="level2"><div
class="li"> Layers are usually transparent (but can be opaque).</div></li></ul></li><li
class="level1"><div
class="li"> A layer contains panels.</div><ul><li
class="level2"><div
class="li"> Panels are containers that impose an alignment on their content (vertical, horizontal, centered)</div></li><li
class="level2"><div
class="li"> Panels can be nested, but not overlap.</div></li><li
class="level2"><div
class="li"> Panels are usually opaque (but can be transparent). ?</div></li></ul></li><li
class="level1"><div
class="li"> A panel can contain images, text fields, buttons, controls.</div></li><li
class="level1"><div
class="li"> Every element has an id to refer to it.</div></li></ul></div><h2><a
name="how_to_use_screens_and_layers">How to Use Screens and Layers</a></h2><div
class="level2"><p> Create an empty helloworld.xml file in the <code>assets/Interfaces/</code> directory of your project.</p><p> Here&#039;s a minimal example showing an empty centered layer on the start screen:</p><pre><span>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span>&lt;nifty xmlns=&quot;http://nifty-gui.sourceforge.net/nifty.xsd&quot; </span>
<span> xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; </span>
<span> xsi:schemaLocation=&quot;http://nifty-gui.sourceforge.net/nifty.xsd
http://nifty-gui.sourceforge.net/nifty.xsd&quot;&gt;</span>
&nbsp;
<span>&lt;screen id=&quot;start&quot; controller=&quot;de.lessvoid.nifty.examples.helloworld.HelloWorldStartScreen&quot;&gt;</span>
<span>&lt;layer id=&quot;layer1&quot; backgroundColor=&quot;#003f&quot; childLayout=&quot;center&quot;&gt;</span>
&lt;!-- ... panels go here... --&gt;
<h1><a>Laying out the GUI in XML</a></h1>
<div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Nifty GUI Concepts</a></div>
</li>
<li><div> <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym> <acronym title="Extensible Markup Language">XML</acronym> Layout</strong> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_layout.html">Nifty GUI Java Layout</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div>
</li>
</ol>
<p>
You can &quot;draw&quot; the <acronym title="Graphical User Interface">GUI</acronym> to the screen by writing <acronym title="Extensible Markup Language">XML</acronym> code (alternatively you can also use Java).
</p>
</div>
<h2><a>Plan Your GUI Layout</a></h2>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/gui-layout-draft.png">
</p>
<p>
In this tutorial, you want to create two game screens: An out-of-game StartScreen that the players see before the game starts; and an in-game <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/HUD_%28video_gaming%29"><param name="text" value="<html><u>HUD</u></html>"><param name="textColor" value="blue"></object> that displays info during the game. Before writing code, you plan the <acronym title="Graphical User Interface">GUI</acronym> layout, either on paper or in a graphic application.
</p>
<p>
The StartScreen contains:
</p>
<ul>
<li><div> The background layer has a centered layout and contains an image.</div>
</li>
<li><div> The top layer has a vertical layout, containing 3 panels: </div>
<ul>
<li><div> The top panel contains a label with the game title, </div>
</li>
<li><div> The middle panel contains a text field with the game description. </div>
</li>
<li><div> The bottom panel has a horizontal layout and contains two more panels:</div>
<ul>
<li><div> The left panel contains a Start button.</div>
</li>
<li><div> The right panel contains a Quit button.</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
The HUD contains:
</p>
<ul>
<li><div> The background layer has a centered layout, and contains a the partially transparent HUD image.</div>
</li>
<li><div> The top layer has a horizontal layout, containing 2 panels: </div>
<ul>
<li><div> The left panel as transparent spacer.</div>
</li>
<li><div> The right panel has a vertical layout containing 2 panels, a label and an image.</div>
</li>
</ul>
</li>
</ul>
</div>
<h2><a>Implement Your GUI Layout</a></h2>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-screen-layer-panel.png">
</p>
<p>
Create an empty screen.xml file in the <code>assets/Interfaces/</code> directory of your project. One <acronym title="Extensible Markup Language">XML</acronym> file can contain several, or even all screens. As a reminder: Nifty displays one screen at a time; a screen contains several layers on top of one another; each layer contains panels that are embedded into another; the panels contain the actual content (text, images, or controls).
</p>
</div>
<h3><a>Make Screens</a></h3>
<div>
<p>
The following minimal <acronym title="Extensible Markup Language">XML</acronym> file contains a start screen and a HUD screen. (Neither has been defined yet.)
</p>
<pre><span>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span>&lt;nifty xmlns=&quot;http://nifty-gui.sourceforge.net/nifty.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; </span>
<span> xsi:schemaLocation=&quot;http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd&quot;&gt;</span>
<span>&lt;screen id=&quot;start&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/screen&gt;</span></span>
<span>&lt;screen id=&quot;hud&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/screen&gt;</span></span>
<span><span>&lt;/nifty&gt;</span></span></pre>
<p>
Every Nifty <acronym title="Graphical User Interface">GUI</acronym> must have a start screen. The others (in this example, the HUD screen) are optional.
</p>
<p>
<strong>Note:</strong> In the following examples, the <acronym title="Extensible Markup Language">XML</acronym> schema header is abbreviated to just <code>&lt;nifty&gt;</code>.
</p>
</div>
<h3><a>Make Layers</a></h3>
<div>
<p>
The following minimal <acronym title="Extensible Markup Language">XML</acronym> file shows how we added layers to the start screen and HUD screen:
</p>
<pre><span><span>&lt;nifty&gt;</span></span>
<span>&lt;screen id=&quot;start&quot;&gt;</span>
<span>&lt;layer id=&quot;background&quot; backgroundColor=&quot;#000f&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/layer&gt;</span></span>
<span>&lt;layer id=&quot;foreground&quot; backgroundColor=&quot;#0000&quot; childLayout=&quot;vertical&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span>
&nbsp;
<span><span>&lt;/nifty&gt;</span></span></pre><p> Into a layer, you add panels (text, images, etc), and specify their properties:</p></div><h3><a
name="panel">Panel</a></h3><div
class="level3"><p> A panels looks like a rectangular colored box.</p><pre>...
<span>&lt;panel height=&quot;25%&quot; width=&quot;35%&quot; align=&quot;center&quot; valign=&quot;center&quot; backgroundColor=&quot;#f60f&quot;</span>
<span> childLayout=&quot;center&quot; visibleToMouse=&quot;true&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
...</pre></div><h3><a
name="text">Text</a></h3><div
class="level3"><pre>...
<span>&lt;text font=&quot;verdana-24-shadow.fnt&quot; text=&quot;Hello World!&quot; align=&quot;center&quot; valign=&quot;center&quot; /&gt;</span>
...</pre><p> or</p><pre>...
<span>&lt;label text=&quot;this is my text&quot; align=&quot;left&quot;/&gt;</span>
...</pre></div><h3><a
name="image">Image</a></h3><div
class="level3"><pre><span>&lt;image filename=&quot;Textures/jme-logo.png&quot; &gt;<span>&lt;/image&gt;</span></span></pre><p> Nifty additionally offers predefined controls – learn more from the NiftyGUI page:</p><ul><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction</a></div></li><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements</a></div></li></ul></div><h2><a
name="effects">Effects</a></h2><div
class="level2"><p> You can register effects to screen elements.</p><ul><li
class="level1"><div
class="li"> Respond to element events such as onStartScreen, onEndScreen, onHover, onFocus, onActive,</div></li><li
class="level1"><div
class="li"> Trigger effects that change movement, blending, size, color, fading, and much more.</div></li></ul><p> Here is an example that moves a panel when the startScreen opens. You place an &lt; effect &gt; tag inside the element that you want to want to be affected.</p><pre>...
<span>&lt;panel height=&quot;25%&quot; width=&quot;35%&quot; ...&gt;</span>
<span><span>&lt;effect&gt;</span></span>
<span>&lt;onStartScreen name=&quot;move&quot; mode=&quot;in&quot; direction=&quot;top&quot; </span>
<span> length=&quot;300&quot; startDelay=&quot;0&quot; inherit=&quot;true&quot;/&gt;</span>
<span><span>&lt;/effect&gt;</span></span>
<span>&lt;screen id=&quot;hud&quot;&gt;</span>
<span>&lt;layer id=&quot;background&quot; backgroundColor=&quot;#000f&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/layer&gt;</span></span>
<span>&lt;layer id=&quot;foreground&quot; backgroundColor=&quot;#0000&quot; childLayout=&quot;vertical&quot;&gt;</span>
&lt;!-- ... --&gt;
<span><span>&lt;/layer&gt;</span></span>
<span><span>&lt;/screen&gt;</span></span>
<span><span>&lt;/nifty&gt;</span></span></pre>
<p>
In a layer, you can now add panels and arrange them. Panels are containers that mark the areas where you want to display text, images, or controls (buttons etc) later.
</p>
</div>
<h3><a>Make Panels</a></h3>
<div>
<p>
A panel is the inner-most container (that will contain the actual content: text, images, or controls). You place panels inside layers. The following panels go into in the <code>start</code> screen&#039;s <code>foreground</code> layer:
</p>
<pre> <span>&lt;panel id=&quot;panel_top&quot; height=&quot;25%&quot; width=&quot;75%&quot; align=&quot;center&quot; childLayout=&quot;center&quot;</span>
<span> backgroundColor=&quot;#f008&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_mid&quot; height=&quot;50%&quot; width=&quot;75%&quot; align=&quot;center&quot; childLayout=&quot;center&quot;</span>
<span> backgroundColor=&quot;#0f08&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_bottom&quot; height=&quot;25%&quot; width=&quot;75%&quot; align=&quot;center&quot; childLayout=&quot;horizontal&quot;</span>
<span> backgroundColor=&quot;#00f8&quot;&gt;</span>
<span>&lt;panel id=&quot;panel_bottom_left&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot; </span>
<span> backgroundColor=&quot;#44f8&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_bottom_right&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;</span>
<span> backgroundColor=&quot;#88f8&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
The following panels go into in the <code>hud</code> screen&#039;s <code>foreground</code> layer:
</p>
<pre> <span>&lt;panel id=&quot;panel_left&quot; width=&quot;80%&quot; height=&quot;100%&quot; childLayout=&quot;vertical&quot; </span>
<span> backgroundColor=&quot;#0f08&quot;&gt;</span>
&lt;!-- spacer --&gt;
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_right&quot; width=&quot;20%&quot; height=&quot;100%&quot; childLayout=&quot;vertical&quot; </span>
<span> backgroundColor=&quot;#00f8&quot; &gt;</span>
<span>&lt;panel id=&quot;panel_top_right1&quot; width=&quot;100%&quot; height=&quot;15%&quot; childLayout=&quot;center&quot;</span>
<span> backgroundColor=&quot;#00f8&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_top_right2&quot; width=&quot;100%&quot; height=&quot;15%&quot; childLayout=&quot;center&quot;</span>
<span> backgroundColor=&quot;#44f8&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span>&lt;panel id=&quot;panel_bot_right&quot; width=&quot;100%&quot; height=&quot;70%&quot; valign=&quot;center&quot;</span>
<span> backgroundColor=&quot;#88f8&quot;&gt;</span>
<span><span>&lt;/panel&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
The result should look as follows:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-panels.png">
</p>
</div>
<h2><a>Adding Content to Panels</a></h2>
<div>
<p>
See also <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Layout_Introduction"><param name="text" value="<html><u>Layout Introduction</u></html>"><param name="textColor" value="blue"></object> on the Nifty <acronym title="Graphical User Interface">GUI</acronym> site.
</p>
</div>
<h3><a>Add Images</a></h3>
<div>
<p>
The start-background.png image is a fullscreen background picture. In the <code>start</code> screen, add the following image element:
</p>
<pre> <span>&lt;layer id=&quot;background&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;image filename=&quot;Interface/tutorial/step2/start-background.png&quot;&gt;<span>&lt;/image&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span></pre>
<p>
The hud-frame.png image is a transparent frame that we use as HUD decoration. In the <code>hud</code> screen, add the following image element:
</p>
<pre> <span>&lt;layer id=&quot;background&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;image filename=&quot;Interface/tutorial/step2/hud-frame.png&quot;&gt;<span>&lt;/image&gt;</span></span>
<span><span>&lt;/layer&gt;</span></span></pre>
<p>
The face1.png image is an image that you want to use as a status icon.
In the <code>hud</code> screen&#039;s <code>foreground</code> layer, add the following image element:
</p>
<pre> <span>&lt;panel id=&quot;panel_bottom_left&quot; height=&quot;75%&quot; width=&quot;20%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;image filename=&quot;Interface/tutorial/step2/face1.png&quot; </span>
<span> valign=&quot;center&quot; align=&quot;center&quot; height=&quot;50%&quot; width=&quot;30%&quot; &gt;</span>
<span><span>&lt;/image&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
This image is scaled to use 50% of the height and 30% of the width of its container.
</p>
</div>
<h3><a>Add Static Text</a></h3>
<div>
<p>
The game title is a typical exmaple of static text. In the <code>start</code> screen, add the following text element:
</p>
<pre> <span>&lt;panel id=&quot;panel_top&quot; height=&quot;25%&quot; width=&quot;75%&quot; align=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;text text=&quot;My Cool Game&quot; font=&quot;Interface/Fonts/Default.fnt&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;</span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
For longer pieces of static text, such as an introduction, you can use wrap=&quot;true&quot;. Add the following text element to the <code>Start screen</code>:
</p>
<pre> <span>&lt;panel id=&quot;panel_mid&quot; height=&quot;50%&quot; width=&quot;75%&quot; align=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;text text=&quot;Here goes some text describing the game and the rules and stuff. Incidentally,
the text is quite long and needs to wrap at the end of lines. ...&quot; </span>
<span> font=&quot;Interface/Fonts/Default.fnt&quot; width=&quot;100%&quot; height=&quot;100%&quot; wrap=&quot;true&quot; /&gt;</span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
The font used is jME3&#039;s default font &quot;Interface/Fonts/Default.fnt&quot; which is included in the jMonkeyEngine.JAR. You can add your own fonts to your own <code>assets/Interface</code> directory.
</p>
</div>
<h3><a>Add Controls</a></h3>
<div>
<p>
Before you can use any control, you must load a Control Definition first. Add the following two lines <em>before</em> your screen definitions:
</p>
<pre> <span>&lt;useControls filename=&quot;nifty-default-controls.xml&quot; /&gt;</span>
<span>&lt;useStyles filename=&quot;nifty-default-styles.xml&quot; /&gt;</span></pre>
</div>
<h4><a>Label Control</a></h4>
<div>
<p>
Use label controls for text that you want to edit dynamically from Java. One example for this is the score display.
In the <code>hud</code> screen&#039;s <code>foreground</code> layer, add the following text element:
</p>
<pre> <span>&lt;panel id=&quot;panel_top_right&quot; height=&quot;100%&quot; width=&quot;15%&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;control name=&quot;label&quot; color=&quot;#000&quot; text=&quot;123&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;</span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
Note that the width and height do not scale the bitmap font, but the make indirectly certain it is centered. If you want a different size for the font, you need to provide an extra bitmap font (they come with fixes sizes and don&#039;t scale well).
</p>
</div>
<h4><a>Button Control</a></h4>
<div>
<p>
Our <acronym title="Graphical User Interface">GUI</acronym> plan asks for two buttons on the start screen. You add the Start and Quit buttons to the bottom panel of the <code>start</code> screen using the <code>&lt;control&gt;</code> element:
</p>
<pre> <span>&lt;panel id=&quot;panel_bottom_left&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;control name=&quot;button&quot; label=&quot;Start&quot; id=&quot;StartButton&quot; align=&quot;center&quot; valign=&quot;center&quot;&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span>
...</pre><p> Playing sounds using nifty is also possible with effects as triggers. Remember to first register the sound you&#039;re going to play:</p><pre>...
<span>&lt;registerSound id=&quot;click&quot; filename=&quot;Sounds/Gui/ButtonClick.ogg&quot; /&gt;</span>
...
<span><span>&lt;label&gt;</span></span>
<span><span>&lt;effect&gt;</span></span>
<span>&lt;onClick name=&quot;playSound&quot; sound=&quot;click&quot;/&gt;</span>
<span><span>&lt;/effect&gt;</span></span>
<span><span>&lt;/label&gt;</span></span>
...</pre><p> Learn more from the NiftyGUI page:</p><ul><li
class="level1"><div
class="li"> <a
href="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects">http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects</a></div></li></ul><hr
/><ol><li
class="level1"><div
class="li"> <strong>Nifty <acronym
title="Graphical User Interface">GUI</acronym> <acronym
title="Extensible Markup Language">XML</acronym> Layout</strong></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> or <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a></div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_java_interaction.html">Interact with the GUI from Java</a></div></li></ol><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_xml_layout?do=export_xhtmlbody">view online version</a></em></p>
<span>&lt;panel id=&quot;panel_bottom_right&quot; height=&quot;50%&quot; width=&quot;50%&quot; valign=&quot;center&quot; childLayout=&quot;center&quot;&gt;</span>
<span>&lt;control name=&quot;button&quot; label=&quot;Quit&quot; id=&quot;QuitButton&quot; align=&quot;center&quot; valign=&quot;center&quot;&gt;</span>
<span><span>&lt;/control&gt;</span></span>
<span><span>&lt;/panel&gt;</span></span></pre>
<p>
Note that these controls don&#039;t do anything yet – we&#039;ll get to that soon.
</p>
</div>
<h4><a>Other Controls</a></h4>
<div>
<p>
Nifty additionally offers many customizable controls such as check boxes, text fields, menus, chats, tabs, … See also <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Elements"><param name="text" value="<html><u>Elements</u></html>"><param name="textColor" value="blue"></object> on the Nifty <acronym title="Graphical User Interface">GUI</acronym> site.
</p>
</div>
<h2><a>Intermediate Result</a></h2>
<div>
<p>
When you preview this code in the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>, our tutorial demo should looks as follows: A start screen with two buttons, and a game screen with a simple HUD frame and a blue cube (which stands for any jME3 game content).
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/nifty-gui-simple-demo.png">
</p>
<p>
Compare this result with the layout draft above.
</p>
</div>
<h2><a>Next Steps</a></h2>
<div>
<p>
Integrate the <acronym title="Graphical User Interface">GUI</acronym> into the game. Typically, you will overlay the <acronym title="Graphical User Interface">GUI</acronym>.
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_overlay.html">Nifty GUI Overlay</a> (recommended)</div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_projection.html">Nifty GUI Projection</a> (optional)</div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>,
<a href="/wiki/doku.php/tag:nifty?do=showtag&amp;tag=tag%3Anifty">nifty</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_xml_layout?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,192 @@
<h1><a>Open Game Finder</a></h1>
<div>
<p>
The Open Game Finder (OGF) by Mark Schrijver can be plugged into any Java game. OGF enables you to find other people playing the same multiplayer game, and join them.
</p>
<ul>
<li><div> Homepage: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/open-game-finder/"><param name="text" value="<html><u>http://code.google.com/p/open-game-finder/</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> Documentation: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/open-game-finder/w/list"><param name="text" value="<html><u>http://code.google.com/p/open-game-finder/w/list</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
Both on the client and the server side of OGF is written purely in Java. OGF has a pluggable architecture and comes with a full set of plugins to get the job done. You can add your own plugins, or replace existing plugins to make them more in line with your game. OGF uses NiftyGUI as the main <acronym title="Graphical User Interface">GUI</acronym> plugin.
</p>
</div>
<h2><a>Installation</a></h2>
<div>
<ol>
<li><div> Go to <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/open-game-finder/downloads/list"><param name="text" value="<html><u>http://code.google.com/p/open-game-finder/downloads/list</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> Download Client-1.0-bin.zip and Server-1.0-bin.zip</div>
</li>
<li><div> Unzip the two files to, for example, your jMonkeyProjects directory.</div>
</li>
</ol>
</div>
<h2><a>Setting up the Database</a></h2>
<div>
<p>
The OGF server uses an embedded Apache Derby database. You have to install the database, this means creating the data files and adding the tables. You can do this straight from the command line by running a script file.
</p>
<ul>
<li><div> On Windows, use installServer.bat to create a new database from scratch. On Mac <acronym title="Operating System">OS</acronym> or Linux, run <code>java -jar lib/Server-0.1.jar install</code> in the Terminal.</div>
</li>
<li><div> On Windows, use updateServer.bat to update the difference between the current state of the database and the way it should be. On Mac <acronym title="Operating System">OS</acronym> and Linux, run <code>java -jar lib/Server-0.1.jar update</code> in the Terminal. <br/>
<strong>This new feature is currently untested.</strong></div>
</li>
</ul>
</div>
<h2><a>Running the server</a></h2>
<div>
<p>
Change into the OGF-Server directory and run the server:
</p>
<ul>
<li><div> On Windows: Run startServer.bat</div>
</li>
<li><div> On Linux and MacOS X: Run <code>java -jar lib/Server-1.0.jar</code> in the Terminal.</div>
</li>
</ul>
<p>
The server is now running and ready to accept connections. <br/>
<strong>Note:</strong> In the alpha release, the server runs on localhost. In the final release, you will be able to configure the host!
</p>
</div>
<h2><a>Running the client</a></h2>
<div>
<ol>
<li><div> Change into the OGF-Client directory and run the client:</div>
<ul>
<li><div> On Windows: Run startClient.bat</div>
</li>
<li><div> On Linux and MacOS X: Run <code>java -jar lib/Client-1.0.jar</code> in the Terminal.</div>
</li>
</ul>
</li>
<li><div> If a Display Settings window appears, you can keep the defaults and click OK.</div>
</li>
</ol>
<p>
A client is now running, connects to the server, and displays a registration/login window.
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/open-game-finder-1.png">
<strong>Note:</strong> You can run several clients on localhost for testing.
</p>
</div>
<h3><a>Client: 1. Registration</a></h3>
<div>
<p>
If clients use OGF for the first time, they need to register.
On the main screen of the client:
</p>
<ol>
<li><div> Click Register</div>
</li>
<li><div> Choose a user name and password (repeat the password).</div>
</li>
<li><div> Select an Avatar image.</div>
</li>
<li><div> Click register to complete the registration.</div>
</li>
</ol>
<p>
The client registers the account and opens the chat window directly.
</p>
</div>
<h3><a>Client: 2. Login</a></h3>
<div>
<p>
If returning clients are already registered to an OGF server, they can log in.
On the main screen of the client:
</p>
<ol>
<li><div> Enter a user name and password that you previously registered.</div>
</li>
<li><div> Click Login</div>
</li>
</ol>
<p>
The client logs you in and opens the chat window.
</p>
</div>
<h3><a>Client: 3. Chat</a></h3>
<div>
<p>
The chat window shows a list of all users logged in to the server. Logged-in users can send public messages, and can receive public messages from others.
</p>
</div>
<h2><a>Connecting to a Game</a></h2>
<div>
<p>
Q: I want to gather players using the OGF client to connect to the game server. How do I start my multiplayer game? <br/>
A: The following sample code demos the typical use case: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/open-game-finder/source/browse/OGF/TRUNK/Client/src/main/java/com/ractoc/opengamefinder/client/OGFClientStartup.java"><param name="text" value="<html><u>OGFClientStartup.java</u></html>"><param name="textColor" value="blue"></object>
<br/>
In a JME3 Application&#039;s init method:
</p>
<ol>
<li><div> Create a com.ractoc.opengamefinder.client.GUIContainer object.</div>
</li>
<li><div> Create a game instance using the GUIContainer (via a ClientFactory).</div>
</li>
<li><div> Check the com.ractoc.pffj.api.BasePluginMessageResult for success or failure.</div>
</li>
</ol>
<p>
After this, continue writing your JME3 init method.
</p>
</div>
<h2><a>Configuration</a></h2>
<div>
<ul>
<li><div> Q: How can I offer more avatars to choose from? <br/>
A: Save the image files in the path <code>jMonkeyProjects/OGF-Client-1.0-bin/OGF/resources/avatars/</code></div>
</li>
<li><div> Q: How do I configure servers addresses? <br/>
A: TBD</div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:open_game_finder?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 18 KiB

@ -1,193 +1,236 @@
<h1><a
name="particle_emmitter_settings">Particle Emmitter Settings</a></h1><div
class="level1"><p> You cannot create a 3D model for delicate things like fire, smoke, or explosions. Particle Emitters are quite an efficient solution to create these kinds of effects: The emitter renders a series of flat orthogonal images and manipulates them in a way that creates the illusion of a anything from a delicate smoke cloud to individual flames, etc.</p><p> Creating an effect involves some trial and error to get the settings <em>just right</em>, and it&#039;s worth exploring the expressiveness of the options described below. <strong>Tip:</strong> Use the Scene Editor in the <a
href="/com/jme3/gde/core/docs/sdk.html">jMonkeyPlatform</a> to design and preview effects.</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:explosion-5.png?id=jme3%3Aadvanced%3Aparticle_emitters"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:particle.png?id=jme3%3Aadvanced%3Aparticle_emitters"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/particle.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:beginner:beginner-effect-fire.png?id=jme3%3Aadvanced%3Aparticle_emitters"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:butterfly-particle-emitter.png?id=jme3%3Aadvanced%3Aparticle_emitters"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png?w=150&amp;h=100" class="media" alt="" width="150" height="100" /></a></p></div><h2><a
name="create_an_emitter">Create an Emitter</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Create one emitter for each effect:<pre>ParticleEmitter explosion = new ParticleEmitter&#40;
&quot;My explosion effect&quot;, ParticleMesh.Type.Triangle, 30&#41;;</pre></div></li><li
class="level1"><div
class="li"> Attach the emitter to the rootNode and position it in the scene:<pre>rootNode.attachChild&#40;explosion&#41;;
explosion.setLocalTranslation&#40;bomb.getLocalTranslation&#40;&#41;&#41;;</pre></div></li><li
class="level1"><div
class="li"> Trigger the effect by calling<pre>explosion.emitAllParticles&#40;&#41;</pre></div></li><li
class="level1"><div
class="li"> End the effect by calling<pre>explosion.killAllParticles&#40;&#41;</pre></div></li></ol><p> Choose one of the following mesh shapes</p><ul><li
class="level1"><div
class="li"> ParticleMesh.Type.Triangle</div></li><li
class="level1"><div
class="li"> ParticleMesh.Type.Point</div></li></ul></div><h2><a
name="configure_parameters">Configure Parameters</a></h2><div
class="level2"><p> Not all of these parameters are required for all kinds of effects. If you don&#039;t specify one of them, a default value will be used.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Parameter</th><th
class="col1 leftalign"> Method</th><th
class="col2"> Default</th><th
class="col3"> Description</th></tr><tr
class="row1"><td
class="col0 leftalign"> number</td><td
class="col1"> <code>setNumParticles()</code></td><td
class="col2 leftalign"></td><td
class="col3"> The maximum number of particles visible at the same time. Specified by user in constructor.</td></tr><tr
class="row2"><td
class="col0 leftalign"> emission rate</td><td
class="col1"> <code>setParticlesPerSec()</code></td><td
class="col2"> 20</td><td
class="col3"> Density of the effect, how many new particles are emitted per second. <br/> Set to zero to control the start of the effect. <br/> Set to a number for a constantly running effect.</td></tr><tr
class="row3"><td
class="col0 leftalign"> size</td><td
class="col1"> <code>setStartSize()</code>, <code>setEndSize()</code></td><td
class="col2"> 0.2f, 2f</td><td
class="col3"> Set both to same value for constant size effect. <br/> Set to different values for shrink/grow effect.</td></tr><tr
class="row4"><td
class="col0 leftalign"> color</td><td
class="col1"> <code>setStartColor()</code>, <code>setEndColor()</code></td><td
class="col2"> gray, darkgray</td><td
class="col3"> Set both to the same color for single-colored effects (e.g. fog). <br/> Set both to different colors for a gradient effect (e.g. fire).</td></tr><tr
class="row5"><td
class="col0 leftalign"> velocity/direction</td><td
class="col1"> <code>setInitialVelocity()</code></td><td
class="col2"> Vector3f(0,0,0)</td><td
class="col3"> A vector specifying how fast or slow particles fly, and it which direction.</td></tr><tr
class="row6"><td
class="col0 leftalign"> randomness</td><td
class="col1"> <code>setVelocityVariation()</code></td><td
class="col2"> 0.2f</td><td
class="col3"> How much the direction/speed (<code>setInitialVelocity()</code>) can vary. <br/> 1 = Maximum variation (particles emit in random directions) <br/> 0 = No variation (particles fly straight with start velocity only).</td></tr><tr
class="row7"><td
class="col0 leftalign"> direction</td><td
class="col1"> <code>setFacingVelocity()</code></td><td
class="col2"> false</td><td
class="col3"> true = Flying particles pitch in the direction they&#039;re flying (e.g. missiles). <br/> false = Particles keep flying rotated the way they started (e.g. debris).</td></tr><tr
class="row8"><td
class="col0 leftalign"> direction</td><td
class="col1"> <code>setRandomAngle()</code></td><td
class="col2"> false</td><td
class="col3"> true = Flying particle should face at a random angle (e.g. explosion). <br/> false = Flying particle flies straight.</td></tr><tr
class="row9"><td
class="col0 leftalign"> direction</td><td
class="col1"> <code>setFaceNormal()</code></td><td
class="col2"> Vector3f.NAN</td><td
class="col3"> Vector3f = Flying particles face in the given direction. <br/> Vector3f.NAN = Flying particles face the camera.</td></tr><tr
class="row10"><td
class="col0 leftalign"> lifetime</td><td
class="col1"> <code>setLowLife()</code></td><td
class="col2"> 3f</td><td
class="col3"> Minimum time period before particles fade</td></tr><tr
class="row11"><td
class="col0 leftalign"> lifetime</td><td
class="col1"> <code>setHighLife()</code></td><td
class="col2"> 7f</td><td
class="col3"> Maximum time period before particles fade</td></tr><tr
class="row12"><td
class="col0 leftalign"> rotation</td><td
class="col1"> <code>setRotateSpeed()</code></td><td
class="col2"> 0f</td><td
class="col3"> 0 = Flying particles don&#039;t spin. <br/> &gt; 0 = How fast particle spins while flying.</td></tr><tr
class="row13"><td
class="col0 leftalign"> gravity</td><td
class="col1"> <code>setGravity()</code></td><td
class="col2"> 0.1f</td><td
class="col3"> &gt;0 = Particles fall &quot;down&quot; (e.g. debris, sparks). <br/> 0.0f = Particles keep flying (e.g. flames, zero g explosion.)</td></tr></table></div><p> Build up you effect by specifying one parameter after the other. If you change several parameters at the same time, it&#039;s difficult to tell which of the values caused which outcome.</p></div><h2><a
name="create_an_effect_material">Create an Effect Material</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/fetch.php?hash=b9f99a&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflash.png"><img
src="/wiki/lib/exe/fetch.php?hash=b9f99a&amp;w=128&amp;h=128&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflash.png" class="mediaright" align="right" alt="" width="128" height="128" /></a></p><p> Use the common Particle.j3md Material Definition to specify the shape of the particles. The shape is only limited by the texture you provide and can be anything – debris, flames, smoke, mosquitoes, leaves, butterflies… be creative.</p><pre> Material mat_flash = new Material&#40;
<h1><a>Particle Emmitter Settings</a></h1>
<div>
<p>
You cannot create a 3D model for delicate things like fire, smoke, or explosions. Particle Emitters are quite an efficient solution to create these kinds of effects: The emitter renders a series of flat orthogonal images and manipulates them in a way that creates the illusion of a anything from a delicate smoke cloud to individual flames, etc.
Creating an effect involves some trial and error to get the settings <em>just right</em>, and it&#039;s worth exploring the expressiveness of the options described below.
</p>
<p>
<strong>Tip:</strong> Use the Scene Editor in the <a href="/com/jme3/gde/core/docs/sdk.html">jMonkeyPlatform</a> to design and preview effects.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/explosion-5.png"> <img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/particle.png"> <img src="nbdocs:/com/jme3/gde/core/docs/jme3/beginner/beginner-effect-fire.png"> <img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/butterfly-particle-emitter.png">
</p>
</div>
<h2><a>Create an Emitter</a></h2>
<div>
<ol>
<li><div> Create one emitter for each effect: <pre>ParticleEmitter explosion = new ParticleEmitter&#40;
&quot;My explosion effect&quot;, ParticleMesh.Type.Triangle, 30&#41;;</pre>
</div>
</li>
<li><div> Attach the emitter to the rootNode and position it in the scene: <pre>rootNode.attachChild&#40;explosion&#41;;
explosion.setLocalTranslation&#40;bomb.getLocalTranslation&#40;&#41;&#41;;</pre>
</div>
</li>
<li><div> Trigger the effect by calling <pre>explosion.emitAllParticles&#40;&#41;</pre>
</div>
</li>
<li><div> End the effect by calling <pre>explosion.killAllParticles&#40;&#41;</pre>
</div>
</li>
</ol>
<p>
Choose one of the following mesh shapes
</p>
<ul>
<li><div> ParticleMesh.Type.Triangle</div>
</li>
<li><div> ParticleMesh.Type.Point</div>
</li>
</ul>
</div>
<h2><a>Configure Parameters</a></h2>
<div>
<p>
Not all of these parameters are required for all kinds of effects. If you don&#039;t specify one of them, a default value will be used.
</p>
<div><table>
<tr>
<th> Parameter </th><th> Method </th><th> Default </th><th> Description </th>
</tr>
<tr>
<td> number </td><td> <code>setNumParticles()</code> </td><td> </td><td> The maximum number of particles visible at the same time. Specified by user in constructor. </td>
</tr>
<tr>
<td> emission rate </td><td> <code>setParticlesPerSec()</code> </td><td> 20 </td><td> Density of the effect, how many new particles are emitted per second. <br/>
Set to zero to control the start/end of the effect. <br/>
Set to a number for a constantly running effect. </td>
</tr>
<tr>
<td> size </td><td> <code>setStartSize()</code>, <code>setEndSize()</code> </td><td> 0.2f, 2f </td><td> The radius of the scaled sprite image. Set both to same value for constant size effect. <br/>
Set to different values for shrink/grow effect. </td>
</tr>
<tr>
<td> color </td><td> <code>setStartColor()</code>, <code>setEndColor()</code> </td><td> gray </td><td> Controls how the opaque (non-black) parts of the texture are colorized. <br/>
Set both to the same color for single-colored effects (e.g. fog, debris). <br/>
Set both to different colors for a gradient effect (e.g. fire). </td>
</tr>
<tr>
<td> direction/velocity </td><td> <code>getParticleInfluencer(). setInitialVelocity(initialVelocity)</code> </td><td> Vector3f(0,0,0) </td><td> A vector specifying the initial direction and speed of particles. The longer the vector, the faster. </td>
</tr>
<tr>
<td> fanning out </td><td> <code>getParticleInfluencer(). setVelocityVariation(variation)</code> </td><td> 0.2f </td><td> How much the direction (<code>setInitialVelocity()</code>) can vary among particles. Use a value between 1 and 0 to create a directed swarm-like cloud of particles. <br/>
1 = Maximum variation, particles emit in random 360° directions (e.g. explosion, butterflies). <br/>
0.5f = particles are emitted within 180° of the initial direction. <br/>
0 = No variation, particles fly in a straight line in direction of start velocity (e.g. lasergun blasts). </td>
</tr>
<tr>
<td> direction <br/>
(pick one)</td><td> <code>setFacingVelocity()</code> </td><td> false </td><td> true = Flying particles pitch in the direction they&#039;re flying (e.g. missiles). <br/>
false = Particles keep flying rotated the way they started (e.g. debris). </td>
</tr>
<tr>
<td> direction <br/>
(pick one)</td><td> <code>setFaceNormal()</code> </td><td> Vector3f.NAN </td><td> Vector3f = Flying particles face in the given direction (e.g. horizontal shockwave faces up = Vector3f.UNIT_Y). <br/>
Vector3f.NAN = Flying particles face the camera. </td>
</tr>
<tr>
<td> lifetime </td><td> <code>setLowLife()</code>, <code>setHighLife()</code> </td><td> 3f, 7f </td><td> The time period before a particle fades is set to a random value between minimum and maximum; minimum must be smaller than maximum. A minimum &lt; 1f makes the effect more busy, a higher minimum looks more steady. Use a maximum &lt; 1f for short bursts, and higher maxima for long lasting swarms or smoke. Set maximum and minimum to similar values to create an evenly spaced effect (e.g. fountain), set the to very different values to create a distorted effect (e.g. fire with individual long flames). </td>
</tr>
<tr>
<td> spinning </td><td> <code>setRotateSpeed()</code> </td><td> 0f </td><td> 0 = Flying particles don&#039;t spin while flying (e.g. smoke, insects, controlled projectiles). <br/>
&gt; 0 = How fast particle spins while flying (e.g. debris, shuriken, missiles out of control). </td>
</tr>
<tr>
<td> rotation </td><td> <code>setRandomAngle()</code> </td><td> false </td><td> true = The particle sprite is rotated at a random angle when it is emitted (e.g. explosion, debris). <br/>
false = Particles fly straight like you drew them in the sprite texture (e.g. insects). </td>
</tr>
<tr>
<td> gravity </td><td> <code>setGravity()</code> </td><td> Vector3f(0.0f,0.1f,0.0f) </td><td> Particles fall in the direction of the vector (e.g. debris, sparks). <br/>
(0,0,0) = Particles keep flying in start direction (e.g. flames, zero-gravity explosion.) </td>
</tr>
<tr>
<td> start area </td><td><code>setShape(new EmitterSphereShape( Vector3f.ZERO, 2f));</code></td><td>EmitterPointShape()</td><td>By default, particles are emitted from the emitters location (a point). You can increase the emitter shape to occupy a sphere, so that the start point of new particles can be anywhere inside the sphere, which makes the effect a bit more irregular.</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [1635-5409] -->
<p>
Build up you effect by specifying one parameter after the other. If you change several parameters at the same time, it&#039;s difficult to tell which of the values caused which outcome.
</p>
</div>
<h2><a>Create an Effect Material</a></h2>
<div>
<p>
<img src="/wiki/lib/exe/fetch.php">
</p>
<p>
Use the common Particle.j3md Material Definition and a texture to specify the shape of the particles. The shape is defined by the texture you provide and can be anything – debris, flames, smoke, mosquitoes, leaves, butterflies… be creative.
</p>
<pre> Material flash_mat = new Material&#40;
assetManager, &quot;Common/MatDefs/Misc/Particle.j3md&quot;&#41;;
mat_flash.setTexture&#40;&quot;Texture&quot;,
flash_mat.setTexture&#40;&quot;Texture&quot;,
assetManager.loadTexture&#40;&quot;Effects/Explosion/flash.png&quot;&#41;&#41;;
flash.setMaterial&#40;debris_mat&#41;;
flash.setMaterial&#40;flash_mat&#41;;
flash.setImagesX&#40;2&#41;; // columns
flash.setImagesY&#40;2&#41;; // rows
flash.setSelectRandomImage&#40;true&#41;;</pre><p> The effect texture can contain Sprite animations – a series of different pictures in equally spaced rows and columns.</p><ul><li
class="level1"><div
class="li"> Specify the number of rows and columns</div></li><li
class="level1"><div
class="li"> Specify whether you want to play the series in order or at random.</div></li></ul><p> Have a look at the following default textures and you will see that you can easily create your own Sprite textures after the same fashion.</p></div><h3><a
name="default_particle_textures">Default Particle Textures</a></h3><div
class="level3"><p> The Material is used together with grayscale texture: The black parts will be transparent and the white parts will be opaque.</p><p> The following effect textures are available by default from <code>test-data.jar</code>. You can also load your own textures from your assets directory.</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Texture Path</th><th
class="col1"> Dimension</th><th
class="col2"> Preview</th></tr><tr
class="row1"><td
class="col0 leftalign"> Effects/Explosion/Debris.png</td><td
class="col1 leftalign"> 3*3</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=3fc13d&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2FDebris.png"><img
src="/wiki/lib/exe/fetch.php?hash=3fc13d&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2FDebris.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row2"><td
class="col0 leftalign"> Effects/Explosion/flame.png</td><td
class="col1 leftalign"> 2*2</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=27332f&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflame.png"><img
src="/wiki/lib/exe/fetch.php?hash=27332f&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflame.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row3"><td
class="col0 leftalign"> Effects/Explosion/flash.png</td><td
class="col1 leftalign"> 2*2</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=b9f99a&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflash.png"><img
src="/wiki/lib/exe/fetch.php?hash=b9f99a&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fflash.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row4"><td
class="col0"> Effects/Explosion/roundspark.png</td><td
class="col1 leftalign"> 1*1</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=467d19&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Froundspark.png"><img
src="/wiki/lib/exe/fetch.php?hash=467d19&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Froundspark.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row5"><td
class="col0 leftalign"> Effects/Explosion/shockwave.png</td><td
class="col1 leftalign"> 1*1</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=fc0cbc&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fshockwave.png"><img
src="/wiki/lib/exe/fetch.php?hash=fc0cbc&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fshockwave.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row6"><td
class="col0"> Effects/Explosion/smoketrail.png</td><td
class="col1 leftalign"> 1*3</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=cb2aa9&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fsmoketrail.png"><img
src="/wiki/lib/exe/fetch.php?hash=cb2aa9&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fsmoketrail.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row7"><td
class="col0 leftalign"> Effects/Explosion/spark.png</td><td
class="col1 leftalign"> 1*1</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=603e22&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fspark.png"><img
src="/wiki/lib/exe/fetch.php?hash=603e22&amp;w=32&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FExplosion%2Fspark.png" class="media" alt="" width="32" height="32" /></a></td></tr><tr
class="row8"><td
class="col0 leftalign"> Effects/Smoke/Smoke.png</td><td
class="col1"> 1*15</td><td
class="col2"> <a
href="/wiki/lib/exe/fetch.php?hash=9adb0f&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FSmoke%2FSmoke.png"><img
src="/wiki/lib/exe/fetch.php?hash=9adb0f&amp;w=96&amp;h=32&amp;media=http%3A%2F%2Fjmonkeyengine.googlecode.com%2Fsvn%2Ftrunk%2Fengine%2Fsrc%2Ftest-data%2FEffects%2FSmoke%2FSmoke.png" class="media" alt="" width="96" height="32" /></a></td></tr></table></div><p> <strong>Tip:</strong> Use the <code>setStartColor()</code>/<code>setEndColor()</code> settings described above to colorize the textures.</p></div><h2><a
name="usage_example">Usage Example</a></h2><div
class="level2"><pre> ParticleEmitter fire = new ParticleEmitter&#40;&quot;Emitter&quot;, ParticleMesh.Type.Triangle, 30&#41;;
flash.setSelectRandomImage&#40;true&#41;;</pre>
<p>
The effect texture can be one image, or contain a sprite animation – a series of slightly different pictures in equally spaced rows and columns. If you choose the sprite animation:
</p>
<ul>
<li><div> Specify the number of rows and columns using setImagesX(2) and setImagesY().</div>
</li>
<li><div> Specify whether you want to play the sprite series in order (animation), or at random (explosion, flame), by setting setSelectRandomImage() true or false.</div>
</li>
</ul>
<p>
<strong>Examples:</strong> Have a look at the following default textures and you will see how you can create your own sprite textures after the same fashion.
</p>
</div>
<h3><a>Default Particle Textures</a></h3>
<div>
<p>
The Material is used together with grayscale texture: The black parts will be transparent and the white parts will be opaque (colored).
The following effect textures are available by default from <code>test-data.jar</code>. You can also load your own textures from your assets directory.
</p>
<div><table>
<tr>
<th> Texture Path </th><th> Dimension </th><th> Preview </th>
</tr>
<tr>
<td> Effects/Explosion/Debris.png </td><td> 3*3 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/flame.png </td><td> 2*2 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/flash.png </td><td> 2*2 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/roundspark.png </td><td> 1*1 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/shockwave.png </td><td> 1*1 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/smoketrail.png </td><td> 1*3 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Explosion/spark.png </td><td> 1*1 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
<tr>
<td> Effects/Smoke/Smoke.png </td><td> 1*15 </td><td> <img src="/wiki/lib/exe/fetch.php"> </td>
</tr>
</table></div>
<!-- EDIT2 TABLE [7232-8509] -->
<p>
<strong>Tip:</strong> Use the <code>setStartColor()</code>/<code>setEndColor()</code> settings described above to colorize the white and gray parts of textures.
</p>
</div>
<h2><a>Usage Example</a></h2>
<div>
<pre> ParticleEmitter fire = new ParticleEmitter&#40;&quot;Emitter&quot;, ParticleMesh.Type.Triangle, 30&#41;;
Material mat_red = new Material&#40;assetManager, &quot;Common/MatDefs/Misc/Particle.j3md&quot;&#41;;
mat_red.setTexture&#40;&quot;Texture&quot;, assetManager.loadTexture&#40;&quot;Effects/Explosion/flame.png&quot;&#41;&#41;;
fire.setMaterial&#40;mat_red&#41;;
fire.setImagesX&#40;2&#41;; fire.setImagesY&#40;2&#41;; // 2x2 texture animation
fire.setEndColor&#40; new ColorRGBA&#40;1f, 0f, 0f, 1f&#41;&#41;; // red
fire.setStartColor&#40;new ColorRGBA&#40;1f, 1f, 0f, 0.5f&#41;&#41;; // yellow
fire.setInitialVelocity&#40;new Vector3f&#40;0, 2, 0&#41;&#41;;
fire.getParticleInfluencer&#40;&#41;.setInitialVelocity&#40;new Vector3f&#40;0,2,0&#41;&#41;;
fire.setStartSize&#40;1.5f&#41;;
fire.setEndSize&#40;0.1f&#41;;
fire.setGravity&#40;0&#41;;
fire.setGravity&#40;0,0,0&#41;;
fire.setLowLife&#40;0.5f&#41;;
fire.setHighLife&#40;3f&#41;;
fire.setVelocityVariation&#40;0.3f&#41;;
rootNode.attachChild&#40;fire&#41;;</pre><p> Browse the full source code of all <a
href="http://code.google.com/p/jmonkeyengine/source/browse/#svn/branches/jme3/src/test/jme3test/effect">effect examples</a> here.</p><hr
/><p> See also: <a
href="/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html">Effects Overview</a></p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:particle_emitters?do=export_xhtmlbody">view online version</a></em></p>
fire.getParticleInfluencer&#40;&#41;.setVelocityVariation&#40;0.3f&#41;;
rootNode.attachChild&#40;fire&#41;;</pre>
<p>
Browse the full source code of all <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/#svn/branches/jme3/src/test/jme3test/effect"><param name="text" value="<html><u>effect examples</u></html>"><param name="textColor" value="blue"></object> here.
</p>
<hr />
<p>
See also: <a href="/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html">Effects Overview</a>
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:particle_emitters?do=export_xhtmlbody">view online version</a></em></p>

@ -1,145 +1,268 @@
<h1><a
name="physicsgravity_collisions_forces">Physics: Gravity, Collisions, Forces</a></h1><div
class="level1"><p> The jMonkeyEngine3 has built-in support for <a
href="http://jbullet.advel.cz">jBullet physics</a> via the <code>com.jme3.bullet</code> package.
<h1><a>Physics: Gravity, Collisions, Forces</a></h1>
<div>
<p>
The jMonkeyEngine3 has built-in support for <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jbullet.advel.cz"><param name="text" value="<html><u>jBullet physics</u></html>"><param name="textColor" value="blue"></object> via the <code>com.jme3.bullet</code> package.
</p>
<p>
Game Physics are used in applications that simulate mass/gravity, collisions, and friction. Think of pool billiard or car racing simulations.
If you are looking for info on how to respond to physics events, read about <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics_listeners.html">Physics Listeners</a>.</p></div><h2><a
name="technical_overview">Technical Overview</a></h2><div
class="level2"><p> Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate the physics space will be stepped multiple times per frame to make up for the missing calculations.
</p>
<p>
If you are looking for info on how to respond to physics events, read about <a href="/com/jme3/gde/core/docs/jme3/advanced/physics_listeners.html">Physics Listeners</a>.
</p>
</div>
<h2><a>Technical Overview</a></h2>
<div>
<p>
Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate the physics space will be stepped multiple times per frame to make up for the missing calculations.
</p>
<p>
A bullet physics space can be created with a BulletAppState. The updating and syncing of the actual physics objects happens in the following way:
A &quot;normal&quot; update loop with physics looks like this:</p><ol><li
class="level1"><div
class="li"> collision callbacks (BulletAppState.update())</div></li><li
class="level1"><div
class="li"> user update (simpleUpdate / update)</div></li><li
class="level1"><div
class="li"> physics to scenegraph syncing/applying (updateLogicalState())</div></li><li
class="level1"><div
class="li"> stepping physics (before / in parallel to Application.render())</div></li></ol><p> When you use physics, 1 unit (1.0f) equals 1 meter, weight is expressed in kilograms, most torque and rotation values are expressed in radians.</p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><p> Full code samples are here:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBrickWall.java">TestBrickWall.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestQ3.java">TestQ3.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestSimplePhysics.java">TestSimplePhysics.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java">TestWalkingChar.java</a></div></li></ul></div><h2><a
name="physics_application">Physics Application</a></h2><div
class="level2"><p> A short overview of how to write a jME application with Physics capabilities:
Do the following once per application to gain access to the <code>physicsSpace</code> object:</p><ol><li
class="level1"><div
class="li"> Make you application extend <code>com.jme3.app.SimpleApplication</code>.</div></li><li
class="level1"><div
class="li"> Create a BulletAppState field:<pre>private BulletAppState bulletAppState;</pre></div></li><li
class="level1"><div
class="li"> Initialize your bulletAppState and attach it to the state manager:<pre>public void simpleInitApp&#40;&#41; &#123;
</p>
<p>
A &quot;normal&quot; update loop with physics looks like this:
</p>
<ol>
<li><div> collision callbacks (BulletAppState.update())</div>
</li>
<li><div> user update (simpleUpdate / update)</div>
</li>
<li><div> physics to scenegraph syncing/applying (updateLogicalState())</div>
</li>
<li><div> stepping physics (before / in parallel to Application.render())</div>
</li>
</ol>
<p>
When you use physics, 1 unit (1.0f) equals 1 meter, weight is expressed in kilograms, most torque and rotation values are expressed in radians.
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
Full code samples are here:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBrickWall.java"><param name="text" value="<html><u>TestBrickWall.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestQ3.java"><param name="text" value="<html><u>TestQ3.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestSimplePhysics.java"><param name="text" value="<html><u>TestSimplePhysics.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java"><param name="text" value="<html><u>TestWalkingChar.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Physics Application</a></h2>
<div>
<p>
A short overview of how to write a jME application with Physics capabilities:
</p>
<p>
Do the following once per application to gain access to the <code>physicsSpace</code> object:
</p>
<ol>
<li><div> Make you application extend <code>com.jme3.app.SimpleApplication</code>.</div>
</li>
<li><div> Create a BulletAppState field: <pre>private BulletAppState bulletAppState;</pre>
</div>
</li>
<li><div> Initialize your bulletAppState and attach it to the state manager: <pre>public void simpleInitApp&#40;&#41; &#123;
bulletAppState = new BulletAppState&#40;&#41;;
stateManager.attach&#40;bulletAppState&#41;;
...</pre></div></li></ol><p> You can also access the BulletAppState via the state manager:</p><pre>stateManager.getState&#40;BulletAppState.class&#41;</pre><p> For each Spatial that you want to be physical:</p><ol><li
class="level1"><div
class="li"> Create a CollisionShape.</div></li><li
class="level1"><div
class="li"> Create a PhysicsControl by supplying the CollisionShape and mass.</div><ul><li
class="level2"><div
class="li"> E.g. <code>com.jme3.bullet.control.RigidBodyControl</code></div></li></ul></li><li
class="level1"><div
class="li"> Add the PhysicsControl to the Spatial.</div></li><li
class="level1"><div
class="li"> Add the PhysicsControl to the physicsSpace object.</div></li><li
class="level1"><div
class="li"> Attach the Spatial to the rootNode, as usual.</div></li><li
class="level1"><div
class="li"> (Optional) Implement the <code>PhysicsCollisionListener</code> interface to respond to <code>PhysicsCollisionEvent</code>s if desired.</div></li></ol></div><h3><a
name="collision_shapes">Collision Shapes</a></h3><div
class="level3"><p> Before you can create a Physics Control, you must create a Collision Shape from the <code>com.jme3.bullet.collision.shapes</code> package.
The Collision Shape is a simplified shape for which physics are easier to calculate than for the real shape of the model. This approach speeds up the simulation greatly.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign"> Shape</th><th
class="col1"> Purpose</th></tr><tr
class="row1"><td
class="col0 leftalign"> BoxCollisionShape</td><td
class="col1"> Box shaped objects such as bricks, crates, simple obstacles. Does not roll.</td></tr><tr
class="row2"><td
class="col0 leftalign"> SphereCollisionShape</td><td
class="col1"> Spherical objects such as balls. Can roll.</td></tr><tr
class="row3"><td
class="col0 leftalign"> CylinderCollisionShape</td><td
class="col1"> Tube-shaped pillars, disc-shaped wheels. Can roll on one side.</td></tr><tr
class="row4"><td
class="col0 leftalign"> CapsuleCollisionShape</td><td
class="col1"> A compound of a cylinder plus two spheres at the top and bottom. Rotated upright, this shape is optimal for character nodes: A cylinder-shaped body does not get stuck at corners and vertical obstacles; the rounded top and bottom do not get stuck on stair steps and ground obstacles. Is locked to stay upright, does not roll.</td></tr><tr
class="row5"><td
class="col0 leftalign"> CompoundCollisionShape</td><td
class="col1"> A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape.</td></tr><tr
class="row6"><td
class="col0 leftalign"> MeshCollisionShape</td><td
class="col1"> A free-form mesh-accurate shape that wraps itself around a mesh. <br/> <strong>Limitations:</strong> Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. The Mesh Collision Shape only works for static obstacles, e.g. for a game level model.</td></tr><tr
class="row7"><td
class="col0 leftalign"> GImpactCollisionShape</td><td
class="col1"> This free-form Mesh Collision Shape can be used for moving objects. Uses <a
href="http://gimpact.sourceforge.net/">http://gimpact.sourceforge.net/</a>. <strong>Limitations:</strong> CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance.</td></tr><tr
class="row8"><td
class="col0"> HeightFieldCollisionShape</td><td
class="col1"> Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.</td></tr><tr
class="row9"><td
class="col0"> HullCollisionShape</td><td
class="col1"> A collision shape that is based on a mesh but is a simplified convex version.</td></tr><tr
class="row10"><td
class="col0"> SimplexCollisionShape</td><td
class="col1">A physical point, line, triangle, or quad Collision Shape, defined by one to four points.</td></tr><tr
class="row11"><td
class="col0"> PlaneCollisionShape</td><td
class="col1"> A 2D plane that can be used as flat solid floor or wall.</td></tr></table></div><p> Pick the right shape for the mesh for what you want to do: If you give a box a sphere collision shape, it will roll; if you give a ball a box collision shape, it will sit on a slope.
Let&#039;s look at the constructor:</p></div><h3><a
name="collision_shape_code_samples">Collision Shape Code Samples</a></h3><div
class="level3"><p> MeshCompoundShape and MeshCollisionShape are both mesh-accurate and are intended for immobile scene objects, such as terrains, buildings, or whole shooter levels. Limitation: Only collisions of non-mesh-accurate shapes (sphere, box, etc) shapes can be detected against mesh-accurate shapes.</p><pre>CompoundCollisionShape myComplexShape =
CollisionShapeFactory.createMeshShape&#40;&#40;Node&#41; myComplexGeometry &#41;;</pre><p> An angular, non-mesh-accurate compound shape:</p><pre>CompoundCollisionShape boxShape =
CollisionShapeFactory.createBoxCompoundShape&#40;&#40;Node&#41; someBox&#41;;</pre><p> SphereCollisionShape, BoxCollisionShape, CapsuleCollisionShape are also not mesh-accurate, but have better performance. The can be added to anything, and collisions between them and any other shape can be detected.</p><pre>SphereCollisionShape sphereShape =
new SphereCollisionShape&#40;1.0f&#41;;</pre></div><h2><a
name="physics_controls">Physics Controls</a></h2><div
class="level2"><p> Available PhysicsControls in the com.jme3.bullet.control package are:</p><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0">Physics Control</th><th
class="col1">Purpose</th></tr><tr
class="row1"><td
class="col0">RigidBodyControl</td><td
class="col1">Use for physical objects in the scene, e.g. projectiles and obstacles – things that are freely affected by physical forces, be it by collision or falling.</td></tr><tr
class="row2"><td
class="col0">CharacterControl</td><td
class="col1">Use for characters (persons, animals) that stand upright, orthogonally to the X/Z plane. When directional forces are applied to a CharacterControl&#039;ed Spatial, it does not tip over (as a RigidBodyControl&#039;ed Spatial would), but it moves upright (as a walking character would).</td></tr><tr
class="row3"><td
class="col0">GhostControl</td><td
class="col1">A GhostControl is a PhysicsControl that detects overlaps with other physical objects. A GhostControl is <em>non-solid</em> and moves with the Spatial it is attached to. Use this for game elements that do not have a visible solid Geometry: Aggro radius, motion detectors, photoelectric sensors, radioactive areas, life-draining ghosts, etc.</td></tr><tr
class="row4"><td
class="col0">VehicleControl <br/> PhysicsVehicleWheel</td><td
class="col1"> Implements <a
href="/com/jme3/gde/core/docs/jme3/advanced/vehicles.html">terrestric vehicle</a> behaviour.</td></tr><tr
class="row5"><td
class="col0">RagDollControl</td><td
class="col1"> Implements <a
href="/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html">Ragdoll</a> behaviour.</td></tr></table></div><p> Bullet Physics are available in jME3 through a several classes. You will use PhysicsControls in 99% of the time.</p></div><h4><a
name="bullet_physics_controls">Bullet Physics Controls</a></h4><div
class="level4"><p> PhysicsControls are the recommended way to use physics in a jME3 application. PhysicsControls are flexible and can be added to any Spatial to make it act according to physical properties. These Control classes directly extend Bullet Physics Objects.
Package: com.jme3.bullet.control</p></div><h4><a
name="bullet_physics_objects">Bullet Physics Objects</a></h4><div
class="level4"><p> Physics Objects are mostly standard Bullet classes like RigidBody, GhostObject etc., that jME3&#039;s other classes are built upon. Advanced users can use these classes to create custom physics functions.
Package: com.jme3.bullet.objects</p></div><h4><a
name="deprecated_bullet_physics_nodes">(Deprecated) Bullet Physics Nodes</a></h4><div
class="level4"><p> <em>Physics Nodes have Bullet Controllers attached and wrap their methods to “simulate” the old physics nodes that were available before alpha-4. The setLocalTranslation/Rotation() info is transferred to the Bullet Objects for simplicity. </em> Do not use Physics Nodes, use PhysicsControls instead.
Package: com.jme3.bullet.nodes</p></div><h3><a
name="physics_controls_code_samples">Physics Controls Code Samples</a></h3><div
class="level3"><p> The various Physics Control constructors expect a Collision Shape (here thingShape) and a mass (a float).</p><pre>RigidBodyControl myControl=new RigidBodyControl&#40; thingShape , 1.0f &#41;;</pre><p> To make the Physics Control visible in the scene, you must attach the Control to a Geometry (e.g. a model named myGeometry):</p><pre>myGeometry.addControl&#40;myControl&#41;;</pre><p> This code sample creates a physical Character:</p><pre>// Load a normal model
...</pre>
</div>
</li>
</ol>
<p>
You can also access the BulletAppState via the state manager:
</p>
<pre>stateManager.getState&#40;BulletAppState.class&#41;</pre>
<p>
For each Spatial that you want to be physical:
</p>
<ol>
<li><div> Create a CollisionShape.</div>
</li>
<li><div> Create a PhysicsControl by supplying the CollisionShape and mass.</div>
<ul>
<li><div> E.g. <code>com.jme3.bullet.control.RigidBodyControl</code></div>
</li>
</ul>
</li>
<li><div> Add the PhysicsControl to the Spatial.</div>
</li>
<li><div> Add the PhysicsControl to the physicsSpace object.</div>
</li>
<li><div> Attach the Spatial to the rootNode, as usual.</div>
</li>
<li><div> (Optional) Implement the <code>PhysicsCollisionListener</code> interface to respond to <code>PhysicsCollisionEvent</code>s if desired.</div>
</li>
</ol>
</div>
<h3><a>Collision Shapes</a></h3>
<div>
<p>
A Collision Shape is a simplified shape for which physics are easier to calculate than for the true shape of the model. This simplication approach speeds up the simulation greatly.
</p>
<p>
Before you can create a Physics Control, you must create a Collision Shape from the <code>com.jme3.bullet.collision.shapes</code> package. (Read the tip under &quot;PhysicsControls Code Samples&quot; to learn how to use default CollisionShapes for Boxes and Spheres.)
</p>
<div><table>
<tr>
<th> Shape </th><th> Purpose </th>
</tr>
<tr>
<td> BoxCollisionShape </td><td> Box shaped objects such as bricks, crates, simple obstacles. Does not roll. </td>
</tr>
<tr>
<td> SphereCollisionShape </td><td> Spherical objects such as balls. Can roll. </td>
</tr>
<tr>
<td> CylinderCollisionShape </td><td> Tube-shaped pillars, disc-shaped wheels. Can roll on one side. </td>
</tr>
<tr>
<td> CapsuleCollisionShape </td><td> A compound of a cylinder plus two spheres at the top and bottom. Rotated upright, this shape is optimal for CharacterControls: A cylinder-shaped body does not get stuck at corners and vertical obstacles; the rounded top and bottom do not get stuck on stair steps and ground obstacles. Is locked to stay upright, does not roll. </td>
</tr>
<tr>
<td> CompoundCollisionShape </td><td> A CompoundCollisionShape allows custom combinations of box/sphere/cylinder shapes to form another more complex shape. </td>
</tr>
<tr>
<td> MeshCollisionShape </td><td> A free-form mesh-accurate shape that wraps itself around a mesh. <br/>
<strong>Limitations:</strong> Only non-mesh collision shapes (sphere, box, cylinder, compound) can collide with mesh-accurate collision shapes. The Mesh Collision Shape only works for static obstacles, e.g. for a game level model. </td>
</tr>
<tr>
<td> GImpactCollisionShape </td><td> This free-form Mesh Collision Shape can be used for moving objects. Uses <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://gimpact.sourceforge.net/"><param name="text" value="<html><u>http://gimpact.sourceforge.net/</u></html>"><param name="textColor" value="blue"></object>. <strong>Limitations:</strong> CPU intensive, use sparingly! We recommend using HullCollisionShapes or CompoundShapes made of simple shapes if you need improved performance. </td>
</tr>
<tr>
<td> HeightFieldCollisionShape </td><td> Optimized Mesh Collision Shape for static terrains. This shape is much faster than a other Free-Form Mesh Shapes. Requires heightmap data.</td>
</tr>
<tr>
<td> HullCollisionShape </td><td> A collision shape that is based on a mesh but is a simplified convex version. </td>
</tr>
<tr>
<td> SimplexCollisionShape </td><td>A physical point, line, triangle, or quad Collision Shape, defined by one to four points.</td>
</tr>
<tr>
<td> PlaneCollisionShape </td><td> A 2D plane that can be used as flat solid floor or wall. </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [3692-5610] -->
<p>
<strong>Tip:</strong> Pick the right shape for the mesh for what you want to do: If you give a box a sphere collision shape, it will roll; if you give a ball a box collision shape, it will sit on a slope. Make collision shapes visible by adding the following line after the bulletAppState initialization:
</p>
<pre>bulletAppState.getPhysicsSpace&#40;&#41;.enableDebug&#40;assetManager&#41;;</pre>
<p>
Let&#039;s look at examples of how to use the CollisionShape constructor:
</p>
</div>
<h3><a>CollisionShape Code Samples</a></h3>
<div>
<p>
MeshCompoundShape and MeshCollisionShape are both mesh-accurate and are intended for immobile scene objects, such as terrains, buildings, or whole shooter levels. Limitation: Only collisions of non-mesh-accurate shapes (sphere, box, etc) shapes can be detected against mesh-accurate shapes.
</p>
<pre>CompoundCollisionShape myComplexShape =
CollisionShapeFactory.createMeshShape&#40;&#40;Node&#41; myComplexGeometry &#41;;</pre>
<p>
An angular, non-mesh-accurate compound shape:
</p>
<pre>CompoundCollisionShape boxShape =
CollisionShapeFactory.createBoxCompoundShape&#40;&#40;Node&#41; someBox&#41;;</pre>
<p>
SphereCollisionShape, BoxCollisionShape, CapsuleCollisionShape are also not mesh-accurate, but have better performance. The can be added to anything, and collisions between them and any other shape can be detected.
</p>
<pre>SphereCollisionShape sphereShape =
new SphereCollisionShape&#40;1.0f&#41;;</pre>
</div>
<h2><a>PhysicsControls</a></h2>
<div>
<p>
BulletPhysics are available in jME3 through Bullet Physics Controls from the com.jme3.bullet.control package. PhysicsControls are the recommended way to use physics in a jME3 application. PhysicsControls are flexible and can be added to any Spatial to make it act according to physical properties. These Control classes directly extend Bullet Physics Objects.
</p>
<div><table>
<tr>
<th>Physics Control</th><th>Purpose</th>
</tr>
<tr>
<td>RigidBodyControl</td><td>Use for physical objects in the scene, e.g. projectiles and obstacles – things that are freely affected by physical forces, be it by collision or falling.</td>
</tr>
<tr>
<td>CharacterControl</td><td>Use for characters (persons, animals) that stand upright, orthogonally to the X/Z plane. When directional forces are applied to a CharacterControl&#039;ed Spatial, it does not tip over (as a RigidBodyControl&#039;ed Spatial would), but it moves upright (as a walking character would).</td>
</tr>
<tr>
<td>GhostControl</td><td>A GhostControl is a PhysicsControl that detects overlaps with other physical objects. A GhostControl is <em>non-solid</em> and moves with the Spatial it is attached to. Use this for game elements that do not have a visible solid Geometry: Aggro radius, motion detectors, photoelectric sensors, radioactive areas, life-draining ghosts, etc. </td>
</tr>
<tr>
<td>VehicleControl <br/>
PhysicsVehicleWheel</td><td> Implements <a href="/com/jme3/gde/core/docs/jme3/advanced/vehicles.html">terrestric vehicle</a> behaviour.</td>
</tr>
<tr>
<td>RagDollControl</td><td> Implements <a href="/com/jme3/gde/core/docs/jme3/advanced/ragdoll.html">Ragdoll</a> behaviour.</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [7377-8399] -->
</div>
<h3><a>PhysicsControls Code Samples</a></h3>
<div>
<p>
The various Physics Control constructors expect a Collision Shape (here thingShape) and a mass (a float).
</p>
<pre>RigidBodyControl myControl=new RigidBodyControl&#40; thingShape , 1.0f &#41;;</pre>
<p>
To make the Physics Control visible in the scene, you must attach the Control to a Geometry (e.g. a model named myGeometry):
</p>
<pre>myGeometry.addControl&#40;myControl&#41;;</pre>
<p>
This code sample creates a physical Character:
</p>
<pre>// Load any model
Node model = &#40;Node&#41; assetManager.loadModel&#40;&quot;Models/myCharacterModel.mesh.xml&quot;&#41;;
rootNode.attachChild&#40;model&#41;;
// Create a appropriate physical shape for it
@ -147,156 +270,262 @@ CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape&#40;1.5f, 6f, 1&#
CharacterControl character_phys = new CharacterControl&#40;capsuleShape, 0.01f&#41;;
// Attach physical properties to model and PhysicsSpace
model.addControl&#40;character_phys&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;character_phys&#41;;</pre><p> Tip: Spheres and Boxes will fall back to their correct default Collision Shape if you don&#039;t specify a shape in the RigidBodyControl constructor. The following creates a box with Box Collision Shape:</p><pre>Box&#40;1,1,1&#41;;
myBox.addControl&#40;new RigidBodyControl&#40; 1.0f &#41;&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;myBox&#41;;</pre></div><h2><a
name="physics_space">Physics Space</a></h2><div
class="level2"><p> The Physics Space is an object in BulletAppState that is like a rootNode for Physics Controls.</p><ol><li
class="level1"><div
class="li"> First specify parameters such as gravity and accuracy.<pre>bulletAppState.getPhysicsSpace&#40;&#41;.setGravity&#40;new Vector3f&#40;0f,-1f,0f&#41;&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.setAccuracy&#40;0.005f&#41;;</pre></div></li><li
class="level1"><div
class="li"> Physics Controls must be added to the PhysicsSpace.<pre>bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;myPhysicsControl&#41;; ...</pre></div></li><li
class="level1"><div
class="li"> Physics Control must be added to their Spatial.<pre>myModel.addControl&#40;myPhysicsControl&#41;; ...</pre></div></li><li
class="level1"><div
class="li"> The Spatial must be attached to the rootNode, as always.<pre>rootNode.attachChild&#40;myModel&#41;; ...</pre></div></li><li
class="level1"><div
class="li"> You remove physical objects from the scene like this:<pre>bulletAppState.getPhysicsSpace&#40;&#41;.remove&#40;myPhysicsControl&#41;;
myModel.removeFromParent&#40;&#41;;</pre></div></li></ol></div><h2><a
name="properties_of_physical_objects">Properties of Physical Objects</a></h2><div
class="level2"><p> On a PhysicsControl, you can set the following physical properties.</p><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0"> RigidBodyControl Method</th><th
class="col1"> Property</th></tr><tr
class="row1"><td
class="col0"> setFriction(1f)</td><td
class="col1"> Friction.</td></tr><tr
class="row2"><td
class="col0"> setMass(1f)</td><td
class="col1"> Sets the mass. Dynamic objects have masses &gt; 0.0f. <br/> Static immobile obstacles (including buildings and terrains) have mass 0.0f.</td></tr><tr
class="row3"><td
class="col0"> setPhysicsLocation()</td><td
class="col1">Positions the object. Do not use setLocalTranslation().</td></tr><tr
class="row4"><td
class="col0"> setPhysicsRotation()</td><td
class="col1">Rotates the object. Do not use setLocalRotate().</td></tr><tr
class="row5"><td
class="col0"> setRestitution(0.0f)</td><td
class="col1"> How bouncy the object is. For a rubber object set this &gt; 0.0f. This setting has an impact on performance.</td></tr><tr
class="row6"><td
class="col0"> setKinematic(true)</td><td
class="col1"> A kinematic node is not affected by gravity, but it is solid and affects other physics objects. It has a mass its position is updated from the spatials translation. You can attach joints to it.</td></tr><tr
class="row7"><td
class="col0"> setGravity(new Vector3f(0f,-1f,0f))</td><td
class="col1"> You can change the gravity of a physics object after it was added to the physics space.</td></tr><tr
class="row8"><td
class="col0"> setCcdMotionThreshold(0.1f)</td><td
class="col1"> The amount of motion in 1 physics tick to trigger the continuous motion detection.</td></tr><tr
class="row9"><th
class="col0"> CharacterControl Method</th><th
class="col1"> Property</th></tr><tr
class="row10"><td
class="col0"> setFallSpeed(1f)</td><td
class="col1"> Fall speed (down)</td></tr><tr
class="row11"><td
class="col0"> setJumpSpeed(1f)</td><td
class="col1"> Jump speed (up)</td></tr><tr
class="row12"><td
class="col0 leftalign"> setMaxSlope(1.5f)</td><td
class="col1"> How steep the slopes are that the character can still climb.</td></tr><tr
class="row13"><td
class="col0"> setUpAxis(1)</td><td
class="col1"> 0 = X axis , 1 = Y axis , 2 = Z axis. E.g. for characters and vehicle, up is usually along the the Y axis.</td></tr><tr
class="row14"><td
class="col0 leftalign"> setGravity(1f)</td><td
class="col1"> You can change the Gravity of a physics object after it was added to the physics space</td></tr></table></div></div><h3><a
name="kinematic_vs_dynamic_vs_static">Kinematic vs Dynamic vs Static</a></h3><div
class="level3"><p> Physical objects…</p><ul><li
class="level1"><div
class="li"> must not overlap.</div></li><li
class="level1"><div
class="li"> can detect collisions and report several values about the impact.</div></li><li
class="level1"><div
class="li"> can respond dynamically or statically or kinematically to collisions.</div></li></ul></div><h4><a
name="dynamic">Dynamic</a></h4><div
class="level4"><p> A dynamic physics object is one that falls when in mid-air, it bounces off obstacles, and is pushed around when it collides with another physical object. It has a mass.</p></div><h4><a
name="static">Static</a></h4><div
class="level4"><p> You can create static physical objects without mass. They are still treated as solid objects, but they cannot be dynamically pushed around. They act as static, immobile attached physical obstacles such as terrains and building models.</p></div><h4><a
name="kinematic">Kinematic</a></h4><div
class="level4"><p> Kinematic RigidBodys have a mass, but they are not affected by gravity. When non-kinematic objects collide with a kinematic object, only the non-kinematic ones are pushed away by the collision. The intesity of the kinematic&#039;s effect against other objects depends on their speed and mass: <code>E<sub>kin</sub> = mass * speed^2</code> (well, approximately, bullet doesn&#039;t use Einsteins formula ;)) <strong>Tip:</strong> Spatials with a kinematic RigidBodyControl can be moved programmatically, e.g. using setLocalTranslation() in the update() loop, or by an Animation Path. You can also &quot;hang them up in mid-air&quot; and attach other PhysicsNodes to them using <a
href="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>.</p><pre>airhook.setKinematic&#40;true&#41;;</pre></div><h2><a
name="forcesmoving_physical_objects">Forces: Moving Physical Objects</a></h2><div
class="level2"><p> Use the following methods to move physics objects.</p><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0"> Method</th><th
class="col1"> Motion</th></tr><tr
class="row1"><td
class="col0"> setAngularVelocity(new Vector3f(0f,0f,1f))</td><td
class="col1"> Set the current rotational speed of the object; the x, y and z component are the speed of rotation around that axis.</td></tr><tr
class="row2"><td
class="col0"> setLinearVelocity(new Vector3f(0f,0f,1f)) </td><td
class="col1"> Set the current linear speed of this object</td></tr><tr
class="row3"><td
class="col0"> setWalkDirection(new Vector3f(0f,0f,0.1f))</td><td
class="col1"> Make a physical character walk (characters are locked to prevent falling over and use a simple physics simulation). Use <code>setWalkDirection(Vector3f.ZERO)</code> to stop a directional motion.</td></tr><tr
class="row4"><td
class="col0"> applyCentralForce(…)</td><td
class="col1 leftalign"> Move (push) the object once with a certain moment, expressed as a Vector3f.</td></tr><tr
class="row5"><td
class="col0"> applyForce(…)</td><td
class="col1"> Move (push) the object once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the object the pushing force hits.</td></tr><tr
class="row6"><td
class="col0"> applyContinuousForce(…)</td><td
class="col1"> Keep moving (pushing) the object with continuous force in one direction, expressed as a Vector3f. Optionally, you can specifiy where on the object the pushing force hits. You can <code>applyContinuousForce(false)</code> to stop the force.</td></tr><tr
class="row7"><td
class="col0"> applyTorque(…)</td><td
class="col1"> Rotate (twist) the object once around its axes, expressed as a Vector3f.</td></tr><tr
class="row8"><td
class="col0"> applyContinuousTorque(…)</td><td
class="col1"> Keep rotating (twisting) the object continuously around its axes, expressed as a Vector3f. You can <code>applyContinuousTorque(false)</code> to stop the rotation.</td></tr><tr
class="row9"><td
class="col0"> applyImpulse(…)</td><td
class="col1"> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball.</td></tr><tr
class="row10"><td
class="col0"> applyTorqueImpulse(…)</td><td
class="col1"> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball.</td></tr><tr
class="row11"><td
class="col0">clearForces()</td><td
class="col1">Cancels out all forces (force, torque) etc and stops the motion.</td></tr></table></div><p> <strong>Note:</strong> It is possible to position physics nodes using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an &quot;impossible state&quot; where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively.
Physics also supports the following features:</p><div
class="table sectionedit5"><table
class="inline"><tr
class="row0"><th
class="col0"> Method</th><th
class="col1"> Property</th></tr><tr
class="row1"><td
class="col0"> setCollisionShape(collisionShape)</td><td
class="col1">Changes the collision shape.</td></tr><tr
class="row2"><td
class="col0"> setCollideWithGroups() <br/> setCollisionGroup() <br/> addCollideWithGroup(COLLISION_GROUP_01) <br/> removeCollideWithGroup(COLLISION_GROUP_01)</td><td
class="col1">Collision Groups are integer bit masks – enums are available in CollisionObject. All physics objects are by default in COLLISION_GROUP_01. Two objects collide when the collideWithGroups set of one contains the collisionGroup of the other.</td></tr><tr
class="row3"><td
class="col0"> setDamping(float, float)</td><td
class="col1">The first value is the linear threshold and the second the angular.</td></tr><tr
class="row4"><td
class="col0"> setAngularFactor(1f)</td><td
class="col1">Set the amount of rotation that will be applied. A value of zero will cancel all rotational force outcome.</td></tr><tr
class="row5"><td
class="col0"> setCcdSweptSphereRadius()</td><td
class="col1">?</td></tr><tr
class="row6"><td
class="col0"> setSleepingThreshold(float,float)</td><td
class="col1">Sets the sleeping thresholds wich define when the object gets deactivated to save ressources. Low values keep the object active when it barely moves. The first value is the linear threshold and the second the angular.</td></tr></table></div></div><h2><a
name="best_practices">Best Practices</a></h2><div
class="level2"><p> You can control the game by triggering forces; or may want to respond to collisions, e.g. by substracting health points, or by playing a sound. To specify how the game responds to physics events, you use <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics_listeners.html">Physics Listeners</a>.
Do not overuse physics nodes. Although the physics nodes are put to “sleep” when they are not moved, creating a world solely out of dynamic physics nodes will quickly bring you to the limits of your computer&#039;s capabilities.
You can use normal non-physical Nodes in the same scene next to physical ones. Use the non-physical ones for non-solid things for which you do not want to detect collisions (ghost, foliage, plants, effects, …). This improves performance.
If you get weird behaviour, such as physical nodes jittering wildy and being ejected for no apparent reason, it usually means you have created an impossible state. Verify that none of the collision shapes overlap. This can happen when you create physical nodes in positions that are too close to other nodes; or if you position a physical node using setLocalTranslation() and it touches another node&#039;s collision shape.
For large static meshes like shooter levels or terrain its best to divide the mesh into multiple physics objects to allow the less cpu intense broadphase to filter out most collision items.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics?do=export_xhtmlbody">view online version</a></em></p>
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;character_phys&#41;;</pre>
<p>
<strong>Tip:</strong> Spheres and Boxes can fall back to the correct default Collision Shape if you do not specify a Collision Shape in the RigidBodyControl constructor. For example, the following creates a box with the correct Box Collision Shape:
</p>
<pre>Box&#40;1,1,1&#41;;
myBox.addControl&#40;new RigidBodyControl&#40; 1.0f &#41;&#41;; // implicit BoxCollisionShape
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;myBox&#41;;</pre>
</div>
<h2><a>Physics Space</a></h2>
<div>
<p>
The Physics Space is an object in BulletAppState that is like a rootNode for Physics Controls.
</p>
<ol>
<li><div> You can specify parameters such as gravity and accuracy.<pre>bulletAppState.getPhysicsSpace&#40;&#41;.setGravity&#40;new Vector3f&#40;0f,-1f,0f&#41;&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.setAccuracy&#40;0.005f&#41;;</pre>
</div>
</li>
<li><div> Add all PhysicsControls to the PhysicsSpace.<pre>bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;myPhysicsControl&#41;; ...</pre>
</div>
</li>
<li><div> Add each PhysicsControl to a Spatial. <pre>myModel.addControl&#40;myPhysicsControl&#41;; ...</pre>
</div>
</li>
<li><div> Attach the Spatial to the rootNode, as always. <pre>rootNode.attachChild&#40;myModel&#41;; ...</pre>
</div>
</li>
</ol>
<p>
You remove physical objects from the scene like this:
</p>
<pre>bulletAppState.getPhysicsSpace&#40;&#41;.remove&#40;myPhysicsControl&#41;;
myModel.removeFromParent&#40;&#41;;</pre>
</div>
<h2><a>Properties of Physical Objects</a></h2>
<div>
<p>
On a PhysicsControl, you can set the following physical properties.
</p>
<div><table>
<tr>
<th> RigidBodyControl Method </th><th> Property </th>
</tr>
<tr>
<td> setFriction(1f) </td><td> Friction. </td>
</tr>
<tr>
<td> setMass(1f) </td><td> Sets the mass. Dynamic objects have masses &gt; 0.0f. <br/>
Static immobile obstacles (including buildings and terrains) have mass 0.0f. </td>
</tr>
<tr>
<td> setPhysicsLocation()</td><td>Positions the object. Do not use setLocalTranslation().</td>
</tr>
<tr>
<td> setPhysicsRotation()</td><td>Rotates the object. Do not use setLocalRotate().</td>
</tr>
<tr>
<td> setRestitution(0.0f) </td><td> How bouncy the object is. For a rubber object set this &gt; 0.0f. This setting has an impact on performance. </td>
</tr>
<tr>
<td> setKinematic(true) </td><td> A kinematic Spatial is not affected by gravity, but it is solid and affects other physics objects. It has a mass its position is updated from the spatials translation. You can attach joints to it. </td>
</tr>
<tr>
<td> setGravity(new Vector3f(0f,-1f,0f)) </td><td> You can change the gravity of a physics object after it was added to the physics space. </td>
</tr>
<tr>
<td> setCcdMotionThreshold(0.1f) </td><td> The amount of motion in 1 physics tick to trigger the continuous motion detection. </td>
</tr>
<tr>
<th> CharacterControl Method </th><th> Property </th>
</tr>
<tr>
<td> setFallSpeed(1f) </td><td> Fall speed (down) </td>
</tr>
<tr>
<td> setJumpSpeed(1f) </td><td> Jump speed (up) </td>
</tr>
<tr>
<td> setMaxSlope(1.5f) </td><td> How steep the slopes are that the character can still climb. </td>
</tr>
<tr>
<td> setUpAxis(1)</td><td> 0 = X axis , 1 = Y axis , 2 = Z axis. E.g. for characters and vehicle, up is usually along the the Y axis.</td>
</tr>
<tr>
<td> setGravity(1f) </td><td> You can change the Gravity of a physics object after it was added to the physics space</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [10696-12109] -->
</div>
<h3><a>Kinematic vs Dynamic vs Static</a></h3>
<div>
<p>
All physical objects…
</p>
<ul>
<li><div> must not overlap.</div>
</li>
<li><div> can detect collisions and report several values about the impact.</div>
</li>
<li><div> can respond dynamically or statically or kinematically to collisions.</div>
</li>
</ul>
<div><table>
<tr>
<td> Property </td><th> Static </th><th> Dynamic </th><th> Kinematic </th>
</tr>
<tr>
<th> Does it have a mass?</th><td>no, 0f</td><td>yes, &gt;0f</td><td>yes, &gt;0f (Inertia is calculated for kinematic objects you need mass to do that)</td>
</tr>
<tr>
<th> How does it move?</th><td>never</td><td>setWalkDirection(), setLinearVelocity(), applyForce(), etc</td><td>setLocalTranslation(), move()</td>
</tr>
<tr>
<th> Can it move and push others?</th><td>no</td><td>yes</td><td>yes</td>
</tr>
<tr>
<th> Is is affected by forces? <br/>
(Falls when it mid-air? Can be pushed by others?)</th><td>no</td><td>yes</td><td>no</td>
</tr>
<tr>
<th> Examples</th><td>Immobile obstacles: Floor, wall, buildings, …</td><td>Interactive objects: Soccer ball, movable crate, falling pillar, …</td><td>Remote-controlled objects: Airship, meteorites, networked NPCs, invisible &quot;airhooks&quot; for hinges and joints.</td>
</tr>
<tr>
<th> How to activate? </th><td>setMass(0f), (By default, objects are not kinematics)</td><td>setMass(1f), setKinematic(false)</td><td>setMass(1f), setKinematic(true)</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [12344-13135] -->
<p>
<strong>Tip:</strong> Typically, Spatials with a kinematic RigidBodyControl are moved programmatically, e.g. using setLocalTranslation() or move() in the update() loop, or by an Animation Path. You can also &quot;hang them up in mid-air&quot; and attach other PhysicsControls to them using <a href="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a>.
</p>
<pre>airhook.setKinematic&#40;true&#41;;</pre>
</div>
<h2><a>Forces: Moving Physical Objects</a></h2>
<div>
<p>
Use the following methods to move physics objects.
</p>
<div><table>
<tr>
<th> PhysicsControl Method </th><th> Motion </th>
</tr>
<tr>
<td> setLinearVelocity(new Vector3f(0f,0f,1f)) </td><td> Set the linear speed of this object. </td>
</tr>
<tr>
<td> setAngularVelocity(new Vector3f(0f,0f,1f)) </td><td> Set the rotational speed of the object; the x, y and z component are the speed of rotation around that axis. </td>
</tr>
<tr>
<td> applyCentralForce(…) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. </td>
</tr>
<tr>
<td> applyForce(…) </td><td> Move (push) the object once with a certain moment, expressed as a Vector3f. Optionally, you can specify where on the object the pushing force hits. </td>
</tr>
<tr>
<td> applyContinuousForce(…) </td><td> Keep moving (pushing) the object with continuous force in one direction, expressed as a Vector3f. Optionally, you can specifiy where on the object the pushing force hits. You can <code>applyContinuousForce(false)</code> to stop the force. </td>
</tr>
<tr>
<td> applyTorque(…) </td><td> Rotate (twist) the object once around its axes, expressed as a Vector3f. </td>
</tr>
<tr>
<td> applyContinuousTorque(…) </td><td> Keep rotating (twisting) the object continuously around its axes, expressed as a Vector3f. You can <code>applyContinuousTorque(false)</code> to stop the rotation.</td>
</tr>
<tr>
<td> applyImpulse(…) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
</tr>
<tr>
<td> applyTorqueImpulse(…) </td><td> An idealised change of momentum. This is the kind of push that you would use on a pool billiard ball. </td>
</tr>
<tr>
<td> setWalkDirection(new Vector3f(0f,0f,0.1f))</td><td> (CharacterControl only) Make a physical character walk. CharacterControls are locked upright to prevent falling over. Use <code>setWalkDirection(Vector3f.ZERO)</code> to stop a directional motion. </td>
</tr>
<tr>
<td>clearForces()</td><td>Cancels out all forces (force, torque) etc and stops the motion.</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [13584-15257] -->
<p>
<strong>Note:</strong> It is technically possible to position PhysicsControls using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an &quot;impossible state&quot; where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively.
</p>
<p>
PhysicsControls also supports the following features:
</p>
<div><table>
<tr>
<th> PhysicsControl Method </th><th> Property </th>
</tr>
<tr>
<td> setCollisionShape(collisionShape)</td><td>Changes the collision shape.</td>
</tr>
<tr>
<td> setCollideWithGroups() <br/>
setCollisionGroup() <br/>
addCollideWithGroup(COLLISION_GROUP_01) <br/>
removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer bit masks – enums are available in CollisionObject. All physics objects are by default in COLLISION_GROUP_01. Two objects collide when the collideWithGroups set of one contains, the Collision Group of the other.</td>
</tr>
<tr>
<td> setDamping(float, float)</td><td>The first value is the linear threshold and the second the angular.</td>
</tr>
<tr>
<td> setAngularFactor(1f)</td><td>Set the amount of rotation that will be applied. A value of zero will cancel all rotational force outcome.</td>
</tr>
<tr>
<td> setCcdSweptSphereRadius()</td><td>?</td>
</tr>
<tr>
<td> setSleepingThreshold(float,float)</td><td>Sets the sleeping thresholds wich define when the object gets deactivated to save ressources. Low values keep the object active when it barely moves. The first value is the linear threshold and the second the angular.</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [15653-16648] -->
</div>
<h2><a>Best Practices</a></h2>
<div>
<ul>
<li><div> You can control the game by triggering forces; or may want to respond to collisions, e.g. by substracting health points, or by playing a sound. To specify how the game responds to physics events, you use <a href="/com/jme3/gde/core/docs/jme3/advanced/physics_listeners.html">Physics Listeners</a>.</div>
</li>
</ul>
<ul>
<li><div> Do not overuse PhysicsControls. Although PhysicsControls are put to “sleep” when they are not moving, creating a world solely out of dynamic physics nodes will quickly bring you to the limits of your computer&#039;s capabilities.</div>
</li>
</ul>
<ul>
<li><div> You can use normal non-physical Spatials in the same scene next to physical ones. Use the non-physical ones for non-solid things for which you do not want to detect collisions (ghost, foliage, plants, effects, …). This improves performance.</div>
</li>
</ul>
<ul>
<li><div> If you get weird behaviour, such as physical nodes jittering wildy and being ejected &quot;for no apparent reason&quot;, it usually means you have created an impossible state. Verify that none of the collision shapes overlap. This can happen when you create physical nodes in positions that are too close to other nodes; or if you position a physical node using setLocalTranslation() and it touches another node&#039;s collision shape. </div>
</li>
</ul>
<ul>
<li><div> For large static meshes like shooter levels or terrain its best to divide the mesh into multiple physics objects to allow the less CPU intense broadphase to filter out most collision items.</div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics?do=export_xhtmlbody">view online version</a></em></p>

@ -1,47 +1,117 @@
<h1><a
name="physics_listeners">Physics Listeners</a></h1><div
class="level1"><p> You can control physical objects by triggering forces. Or maybe you want to respond to collisions, e.g. by substracting health points, or by playing a sound. To specify how the game responds to such physics events, you use Physics Listeners.</p></div><h2><a
name="physics_tick_listener">Physics Tick Listener</a></h2><div
class="level2"><p> The jBullet Physics implementation is stepped at a constant 60 physics ticks per second frame rate.
Applying forces or checking for overlaps only has an effect right at a physics update cycle, which is not every frame. If you do physics interactions at arbitrary spots in the simpleUpdate() loop, calls will be dropped at irregular intervals, because they happen out of cycle.</p></div><h3><a
name="when_not_to_use_tick_listener">When (Not) to Use Tick Listener?</a></h3><div
class="level3"><p> When you write game mechanics that apply forces, you must implement a tick listener (com.jme3.bullet.PhysicsTickListener) for it. The tick listener makes certain the forces are not dropped, but applied in time for the next physics tick.
<h1><a>Physics Listeners</a></h1>
<div>
<p>
You can control physical objects by triggering forces. Or maybe you want to respond to collisions, e.g. by substracting health points, or by playing a sound. To specify how the game responds to such physics events, you use Physics Listeners.
</p>
</div>
<h2><a>Physics Tick Listener</a></h2>
<div>
<p>
The jBullet Physics implementation is stepped at a constant 60 physics ticks per second frame rate.
Applying forces or checking for overlaps only has an effect right at a physics update cycle, which is not every frame. If you do physics interactions at arbitrary spots in the simpleUpdate() loop, calls will be dropped at irregular intervals, because they happen out of cycle.
</p>
</div>
<h3><a>When (Not) to Use Tick Listener?</a></h3>
<div>
<p>
When you write game mechanics that apply forces, you must implement a tick listener (com.jme3.bullet.PhysicsTickListener) for it. The tick listener makes certain the forces are not dropped, but applied in time for the next physics tick.
Also, when you check for overlaps of physical objects with a PhysicsGhostObject, you cannot just go <code>physicsSpace.add(ghost); ghost.getOverLappingObjects()</code> somewhere. You have to make certain 1 physics tick has passed before the overlapping objects list is filled with data. Again, the PhysicsTickListener does that for you.
When your game mechanics however just poll the current state (e.g. location) of physical objects, or if you only use the Ghost control like a sphere trigger, then you don&#039;t need a PhysicsTickListener.</p></div><h3><a
name="how_to_listen_to_physics_ticks">How to Listen to Physics Ticks</a></h3><div
class="level3"><p> Here&#039;s is the declaration of an examplary Physics Control that listens to ticks.</p><pre>public class MyCustomControl
extends RigidBodyControl implements PhysicsTickListener &#123; ... &#125;</pre><p> When you implement the interface, you have to implement preTick() and postTick() methods.</p><ul><li
class="level1"><div
class="li"> <code>prePhysicsTick()</code> is called before the step, here you apply forces (change the state).</div></li><li
class="level1"><div
class="li"> <code>physicsTick()</code> is called after the step, here you poll the results (get the current state).</div></li></ul><pre>@override
When your game mechanics however just poll the current state (e.g. location) of physical objects, or if you only use the Ghost control like a sphere trigger, then you don&#039;t need a PhysicsTickListener.
</p>
</div>
<h3><a>How to Listen to Physics Ticks</a></h3>
<div>
<p>
Here&#039;s is the declaration of an examplary Physics Control that listens to ticks.
</p>
<pre>public class MyCustomControl
extends RigidBodyControl implements PhysicsTickListener &#123; ... &#125;</pre>
<p>
When you implement the interface, you have to implement preTick() and postTick() methods.
</p>
<ul>
<li><div> <code>prePhysicsTick()</code> is called before the step, here you apply forces (change the state).</div>
</li>
<li><div> <code>physicsTick()</code> is called after the step, here you poll the results (get the current state).</div>
</li>
</ul>
<pre>@override
public void prePhysicsTick&#40;PhysicsSpace space, float f&#41;&#123;
// apply state changes ...
&#125;
@override
public void physicsTick&#40;PhysicsSpace space, float f&#41;&#123;
// poll game state ...
&#125;</pre></div><h2><a
name="physics_collision_listener">Physics Collision Listener</a></h2><div
class="level2"></div><h3><a
name="when_not_to_use_collision_listener">When (Not) to Use Collision Listener</a></h3><div
class="level3"><p> If you do not implement the Collision Listener interface (com.jme3.bullet.collision.PhysicsCollisionListener), a collisions will just mean that physical forces are applied automatically. If you just want &quot;Balls rolling, bricks falling&quot; you do not need a listener.
If however you want to respond to a collision event (com.jme3.bullet.collision.PhysicsCollisionEvent) with a custom action, then you need to implement the PhysicsCollisionListener interface. Typical actions triggered by collisions include:</p><ul><li
class="level1"><div
class="li"> Increasing a counter (e.g. score points)</div></li><li
class="level1"><div
class="li"> Decreasing a counter (e.g. health points)</div></li><li
class="level1"><div
class="li"> Triggering an effect (e.g. explosion)</div></li><li
class="level1"><div
class="li"> Playing a sound (e.g. explosion, ouch)</div></li><li
class="level1"><div
class="li"> … and countless more, depending on your game</div></li></ul></div><h3><a
name="how_to_listen_to_collisions">How to Listen to Collisions</a></h3><div
class="level3"><p> Again, here&#039;s the example declaration of a Physics Control that uses a collision listener.</p><pre>public class MyCustomControl
&#125;</pre>
</div>
<h2><a>Physics Collision Listener</a></h2>
<div>
</div>
<h3><a>When (Not) to Use Collision Listener</a></h3>
<div>
<p>
If you do not implement the Collision Listener interface (com.jme3.bullet.collision.PhysicsCollisionListener), a collisions will just mean that physical forces are applied automatically. If you just want &quot;Balls rolling, bricks falling&quot; you do not need a listener.
If however you want to respond to a collision event (com.jme3.bullet.collision.PhysicsCollisionEvent) with a custom action, then you need to implement the PhysicsCollisionListener interface. Typical actions triggered by collisions include:
</p>
<ul>
<li><div> Increasing a counter (e.g. score points)</div>
</li>
<li><div> Decreasing a counter (e.g. health points)</div>
</li>
<li><div> Triggering an effect (e.g. explosion)</div>
</li>
<li><div> Playing a sound (e.g. explosion, ouch)</div>
</li>
<li><div> … and countless more, depending on your game</div>
</li>
</ul>
</div>
<h3><a>How to Listen to Collisions</a></h3>
<div>
<p>
You need to add the PhysicsCollisionListener to the physics space before collisions will be listened for. Again, here&#039;s the example declaration of a Physics Control that uses a collision listener.
</p>
<pre>public class MyCustomControl
extends RigidBodyControl
implements PhysicsCollisionListener &#123; ... &#125;</pre><p> To respond to the PhysicsCollisionEvent you have to override the <code>collision()</code> method. This gives you access to the event object. Mostly you will be interested in the identity of any two nodes that collided: <code>event.getNodeA()</code> and <code>event.getNodeB()</code>.
After you identify the colliding nodes, specify the action to trigger when this pair collides. Note that you cannot know which one will be Node A or Node B, you have to deal with either variant.</p><pre> public void collision&#40;PhysicsCollisionEvent event&#41; &#123;
implements PhysicsCollisionListener &#123;
public MyCustomControl&#40;&#41; &#123;
bulletAppState.getPhysicsSpace&#40;&#41;.addCollisionListener&#40;this&#41;;
...
&#125;</pre>
<p>
To respond to the PhysicsCollisionEvent you have to override the <code>collision()</code> method. This gives you access to the event object. Mostly you will be interested in the identity of any two nodes that collided: <code>event.getNodeA()</code> and <code>event.getNodeB()</code>.
After you identify the colliding nodes, specify the action to trigger when this pair collides. Note that you cannot know which one will be Node A or Node B, you have to deal with either variant.
</p>
<pre> public void collision&#40;PhysicsCollisionEvent event&#41; &#123;
if &#40; event.getNodeA&#40;&#41;.getName&#40;&#41;.equals&#40;&quot;player&quot;&#41; &#41; &#123;
final Node node = event.getNodeA&#40;&#41;;
/** ... do something with the node ... */
@ -49,31 +119,52 @@ After you identify the colliding nodes, specify the action to trigger when this
final Node node = event.getNodeB&#40;&#41;;
/** ... do something with the node ... */
&#125;
&#125;</pre><p><p><div
class="noteimportant">Note that after the collision() method ends, the PhysicsCollisionEvent is cleared. You must get all objects and values you need within the collision() method.</div></p></p></div><h3><a
name="reading_details_from_a_physicscollisionevent">Reading Details From a PhysicsCollisionEvent</a></h3><div
class="level3"><p> The PhysicsCollisionEvent <code>event</code> gives you access to detailed information about the collision. You already know the event objects can identify which nodes collided, but it even knows how hard they collided:</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0 leftalign">Method</th><th
class="col1">Purpose</th></tr><tr
class="row1"><td
class="col0 leftalign"> getObjectA() <br/> getObjectB()</td><td
class="col1"> The two participants in the collision. You cannot know in advance whether some node will be recorded as A or B, you always have to consider both cases.</td></tr><tr
class="row2"><td
class="col0 leftalign"> getAppliedImpulse()</td><td
class="col1"> A float value representing the collision impulse</td></tr><tr
class="row3"><td
class="col0 leftalign"> getAppliedImpulseLateral1()</td><td
class="col1"> A float value representing the lateral collision impulse</td></tr><tr
class="row4"><td
class="col0 leftalign"> getAppliedImpulseLateral2()</td><td
class="col1"> A float value representing the lateral collision impulse</td></tr><tr
class="row5"><td
class="col0 leftalign"> getCombinedFriction()</td><td
class="col1"> A float value representing the collision friction</td></tr><tr
class="row6"><td
class="col0 leftalign"> getCombinedRestitution()</td><td
class="col1"> A float value representing the collision restitution (bounciness)</td></tr></table></div><p> Note that after the collision method has been called the object is not valid anymore so you should copy any data you want to keep into local variables.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics_listeners?do=export_xhtmlbody">view online version</a></em></p>
&#125;</pre>
<p>
<p><div>Note that after the collision() method ends, the PhysicsCollisionEvent is cleared. You must get all objects and values you need within the collision() method.
</div></p>
</p>
</div>
<h3><a>Reading Details From a PhysicsCollisionEvent</a></h3>
<div>
<p>
The PhysicsCollisionEvent <code>event</code> gives you access to detailed information about the collision. You already know the event objects can identify which nodes collided, but it even knows how hard they collided:
</p>
<div><table>
<tr>
<th>Method </th><th>Purpose</th>
</tr>
<tr>
<td> getObjectA() <br/>
getObjectB() </td><td> The two participants in the collision. You cannot know in advance whether some node will be recorded as A or B, you always have to consider both cases. </td>
</tr>
<tr>
<td> getAppliedImpulse() </td><td> A float value representing the collision impulse </td>
</tr>
<tr>
<td> getAppliedImpulseLateral1() </td><td> A float value representing the lateral collision impulse </td>
</tr>
<tr>
<td> getAppliedImpulseLateral2() </td><td> A float value representing the lateral collision impulse </td>
</tr>
<tr>
<td> getCombinedFriction() </td><td> A float value representing the collision friction </td>
</tr>
<tr>
<td> getCombinedRestitution() </td><td> A float value representing the collision restitution (bounciness) </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [4836-5521] -->
<p>
Note that after the collision method has been called the object is not valid anymore so you should copy any data you want to keep into local variables.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics_listeners?do=export_xhtmlbody">view online version</a></em></p>

@ -1,24 +1,89 @@
<h1><a
name="rendering_water_as_post-process_effect">Rendering Water as Post-Process Effect</a></h1><div
class="level1"><p> This awesome water effect is highly configurable and can render any type of water. It is is based on <a
href="http://www.gamedev.net/page/reference/index.html/_//feature/fprogramming/rendering-water-as-a-post-process-effect-r2642">Wojciech Toman’s Rendering Water as a Post-process Effect</a> published on gamedev.net. Here&#039;s a video:</p><p> <a
href="http://www.youtube.com/watch?v=AWlUzgRN3Pc"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post.png" class="mediacenter" alt="" /></a></p></div><h2><a
name="the_theory">The Theory</a></h2><div
class="level2"><p> In this article the author uses the effect in a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen’s pixels position in view space, and a texture of the rendered scene).</p><p> After some calculation this allows to reconstruct the position in world space for each pixel on the screen. If a pixel is under a given water height, let’s render it as a blue pixel! Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction.</p><p> The GameDev.net article describes how those effects are achieved, but the main idea is to generate waves from a height map, create ripples from a normal map, blend in the foam texture when the water depth is below a certain height, compute the refraction color with a clever color extinction algorithm, and then, display the reflection and specular effect by computing a Fresnel term (like in standard water effect). In addition this effect, allow to blend the water shore with the ground to avoid the hard edges effect of classic water effects based on grids or quads.</p></div><h2><a
name="how_did_we_implement_it_in_jme3">How Did We Implement it in jME3?</a></h2><div
class="level2"><p> jME3 default behavior is to use a forward rendering process, so there is no position buffer rendered that we can take advantage of. But while rendering the main scene to a frame buffer in the FilterPostPorcessor, we can write the hardware depth buffer to a texture, with nearly no additional cost.</p><p> I won’t go into the details of this, but there are several ways of reconstructing the world space position of a pixel from the depth buffer. The computational cost is higher than just fetching the position form a position buffer, but the bandwidth and the memory required is a lot lower.</p><p> We have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel… We’re good to go!</p><p> See also: <a
href="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/#comment-609">JME3&#039;s Water Post-Process Effect</a> by Nehon</p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><p> There are two test cases in the jME3 repository:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWater.java">jme3/src/test/jme3test/water/TestPostWater.java</a> (ocean island)</div></li></ul><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWaterLake.java">jme3/src/test/jme3test/water/TestPostWaterLake.java</a> (calm and muddy water pond)</div></li></ul></div><h3><a
name="using_the_water_filter">Using the Water Filter</a></h3><div
class="level3"><p> In the <code>simpleInitApp()</code> method, you attach your scene to the rootNode, typically a terrain with a sky. Remember to add a directional light, since the water relies on the light direction vector. The WaterFilter constrcutor expects a node with the scene attached that should be reflected in the water, and vector information from the light source&#039;s direction.</p><p> This is how you use the water filter post-processor code in your code:</p><pre>private FilterPostProcessor fpp;
<h1><a>Rendering Water as Post-Process Effect</a></h1>
<div>
<p>
The awesome SeaMonkey water Filter is highly configurable. It can render any type of water and also simulates the underwater part of the effect, including &quot;caustics&quot;. It is is based on <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.gamedev.net/page/reference/index.html/_//feature/fprogramming/rendering-water-as-a-post-process-effect-r2642"><param name="text" value="<html><u>Wojciech Toman’s Rendering Water as a Post-process Effect</u></html>"><param name="textColor" value="blue"></object> published on gamedev.net. Here&#039;s a video:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post.png">
</p>
</div>
<h2><a>The Theory</a></h2>
<div>
<p>
The effect is part of a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen’s pixels position in view space, and a texture of the rendered scene).
</p>
<p>
After some calculation, this allows to reconstruct the position in world space for each pixel on the screen. &quot;If a pixel is under a given water height, let’s render it as a blue pixel!&quot; Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction.
</p>
<p>
The GameDev.net article describes how those effects are achieved, but the main idea is to generate waves from a height map, create ripples from a normal map, blend in the foam texture when the water depth is below a certain height, compute the refraction color with a clever color extinction algorithm, and then, display the reflection and specular effect by computing a Fresnel term (like in the simple water effect). In addition, this effect allows to blend the water shore with the ground to avoid the hard edges of classic water effects based on grids or quads.
</p>
</div>
<h2><a>How Did We Implement it in jME3?</a></h2>
<div>
<p>
jME3 default behavior is to use a forward rendering process, so there is no position buffer rendered that we can take advantage of. But while rendering the main scene to a frame buffer in the FilterPostPorcessor, we can write the hardware depth buffer to a texture, with nearly no additional cost.
</p>
<p>
There are several ways of reconstructing the world space position of a pixel from the depth buffer. The computational cost is higher than just fetching the position from a position buffer, but the bandwidth and the memory required is a lot lower.
</p>
<p>
Now we have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel. We’re good to go!
</p>
<p>
– Nehon
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
There are two test cases in the jME3 repository:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWater.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestPostWater.java</u></html>"><param name="textColor" value="blue"></object> (ocean island)</div>
</li>
</ul>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/water/TestPostWaterLake.java"><param name="text" value="<html><u>jme3/src/test/jme3test/water/TestPostWaterLake.java</u></html>"><param name="textColor" value="blue"></object> (calm and muddy water pond)</div>
</li>
</ul>
</div>
<h3><a>Using the Water Filter</a></h3>
<div>
<p>
In the <code>simpleInitApp()</code> method, you attach your scene to the rootNode, typically a terrain with a sky. Remember to add a directional light, since the water relies on the light direction vector. The WaterFilter constrcutor expects a node with the scene attached that should be reflected in the water, and vector information from the light source&#039;s direction.
</p>
<p>
This is how you use the water filter post-processor code in your code:
</p>
<pre>private FilterPostProcessor fpp;
private WaterFilter water;
private Vector3f lightDir = new Vector3f&#40;-4.9f, -1.3f, 5.9f&#41;; // same as light source
private float initialWaterHeight = 0.8f; // choose a value for your scene
@ -32,9 +97,22 @@ public void simpleInitApp&#40;&#41; &#123;
fpp.addFilter&#40;water&#41;;
viewPort.addProcessor&#40;fpp&#41;;
...
&#125;</pre><p> Usually you make the water reflect everything attached to the rootNode. But you can also give a custom node (a subnode of the rootNode) to the WaterFilter constructor that has only a subset of scene nodes attached. This would be a relevant optimization if you have lots of nodes that are far away from the water, or covered, and will never be reflected.</p></div><h3><a
name="optionalwaves">Optional: Waves</a></h3><div
class="level3"><p> If you want waves, set the water height in the update loop. We reuse the initialWaterHeight variable, and repeatedly reset the waterHeight value according to time. This causes the waves.</p><pre>private float time = 0.0f;
&#125;</pre>
<p>
Usually you make the water reflect everything attached to the rootNode. But you can also give a custom node (a subnode of the rootNode) to the WaterFilter constructor that has only a subset of scene nodes attached. This would be a relevant optimization if you have lots of nodes that are far away from the water, or covered, and will never be reflected.
</p>
</div>
<h3><a>Optional: Waves</a></h3>
<div>
<p>
If you want waves, set the water height in the update loop. We reuse the initialWaterHeight variable, and repeatedly reset the waterHeight value according to time. This causes the waves.
</p>
<pre>private float time = 0.0f;
private float waterHeight = 0.0f;
&nbsp;
@Override
@ -43,155 +121,158 @@ public void simpleUpdate&#40;float tpf&#41; &#123;
time += tpf;
waterHeight = &#40;float&#41; Math.cos&#40;&#40;&#40;time * 0.6f&#41; % FastMath.TWO_PI&#41;&#41; * 1.5f;
water.setWaterHeight&#40;initialWaterHeight + waterHeight&#41;;
&#125;</pre></div><h3><a
name="optionalwater_wave_and_color_effects">Optional: Water Wave and Color Effects</a></h3><div
class="level3"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:water-post-muddy.png?id=jme3%3Aadvanced%3Apost-processor_water"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png?w=220&amp;h=172" class="mediacenter" alt="" width="220" height="172" /></a></p><p> All these effects are optional. Every setter also has a getter.</p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><th
class="col0"> Water method example</th><th
class="col1">Effects: Waves</th><th
class="col2">Default</th></tr><tr
class="row1"><td
class="col0">water.setWaterHeight(-6);</td><td
class="col1">Use this waterheight method for causing waves.</td><td
class="col2">0.0f</td></tr><tr
class="row2"><td
class="col0">water.setMaxAmplitude(0.3f);</td><td
class="col1">How high the highest waves are.</td><td
class="col2">1.0f</td></tr><tr
class="row3"><td
class="col0">water.setWaveScale(0.008f);</td><td
class="col1">Sets the scale factor of the waves height map. The smaller the value, the bigger the waves!</td><td
class="col2"> 0.005f</td></tr><tr
class="row4"><td
class="col0">water.setWindDirection(new Vector2f(0,1))</td><td
class="col1">Sets the wind direction, which is the direction where the waves move</td><td
class="col2">Vector2f(0.0f, -1.0f)</td></tr><tr
class="row5"><td
class="col0">water.setSpeed(0.7f);</td><td
class="col1">How fast the waves move. Set it to 0.0f for still water.</td><td
class="col2">1.0f</td></tr><tr
class="row6"><td
class="col0">water.setHeightTexture( (Texture2D) <br/> manager.loadTexture(&quot;Textures/waveheight.png&quot;) )</td><td
class="col1">This height map describes the shape of the waves</td><td
class="col2">&quot;Common/MatDefs/Water/Textures/heightmap.jpg&quot;</td></tr><tr
class="row7"><td
class="col0">water.setNormalTexture( (Texture2D) <br/> manager.loadTexture(&quot;Textures/wavenormals.png&quot;) )</td><td
class="col1">This normal map describes the shape of the waves</td><td
class="col2">&quot;Common/MatDefs/Water/Textures/gradient_map.jpg&quot;</td></tr><tr
class="row8"><td
class="col0">water.setUseRipples(false);</td><td
class="col1">Switches the ripples effect on or off.</td><td
class="col2">true</td></tr><tr
class="row9"><td
class="col0">water.setNormalScale(0.5f)</td><td
class="col1">Sets the normal scaling factors to apply to the normal map. The higher the value, the more small ripples will be visible on the waves.</td><td
class="col2">1.0f</td></tr></table></div><div
class="table sectionedit2"><table
class="inline"><tr
class="row0"><th
class="col0"> Water method example</th><th
class="col1"> Effects: Color</th><th
class="col2">Default</th></tr><tr
class="row1"><td
class="col0">water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f))</td><td
class="col1">Usually you set this to the same as the light source&#039;s direction. Use this to set the light direction if the sun is moving.</td><td
class="col2">Value given to WaterFilter() constructor.</td></tr><tr
class="row2"><td
class="col0">water.setLightColor(ColorRGBA.White)</td><td
class="col1">Usually you set this to the same as the light source&#039;s color.</td><td
class="col2">RGBA.White</td></tr><tr
class="row3"><td
class="col0">water.setWaterColor(ColorRGBA.Brown.mult(2.0f));</td><td
class="col1">Sets the main water color.</td><td
class="col2">greenish blue <br/> Vector3f(0.0f,0.5f,0.5f,1.0f)</td></tr><tr
class="row4"><td
class="col0">water.setDeepWaterColor(ColorRGBA.Brown);</td><td
class="col1">Sets the deep water color.</td><td
class="col2">dark blue <br/> Vector3f(0.0f, 0.0f,0.2f,1.0f)</td></tr><tr
class="row5"><td
class="col0">water.setWaterTransparency(0.2f);</td><td
class="col1">Sets how fast colors fade out. use this to control how clear (e.g. 0.05f) or muddy (0.2f) water is.</td><td
class="col2"> 0.1f</td></tr><tr
class="row6"><td
class="col0">water.setColorExtinction(new Vector3f(10f,20f,30f));</td><td
class="col1">Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to &quot;muddy&quot; the water.</td><td
class="col2">Vector3f(5f,20f,30f)</td></tr></table></div><div
class="table sectionedit3"><table
class="inline"><tr
class="row0"><th
class="col0"> Water method example</th><th
class="col1"> Effects: Shore</th><th
class="col2">Default</th></tr><tr
class="row1"><td
class="col0">water.setShoreHardness(1.0f);</td><td
class="col1">Sets how soft the transition between shore and water should be. High values mean a harder transition between shore and water.</td><td
class="col2">0.1f</td></tr><tr
class="row2"><td
class="col0">water.setUseHQShoreline(false);</td><td
class="col1">Renders shoreline with better quality ?</td><td
class="col2">true</td></tr></table></div><div
class="table sectionedit4"><table
class="inline"><tr
class="row0"><th
class="col0"> Water method example</th><th
class="col1"> Effects: Foam</th><th
class="col2">Default</th></tr><tr
class="row1"><td
class="col0">water.setUseFoam(false);</td><td
class="col1">Switches the white foam on or off</td><td
class="col2">true</td></tr><tr
class="row2"><td
class="col0">water.setFoamHardness(0.5f)</td><td
class="col1">Sets how much the foam will blend with the shore to avoid a hard edged water plane.</td><td
class="col2">1.0f</td></tr><tr
class="row3"><td
class="col0">water.setFoamExistence(new Vector3f(0.5f,5f,1.0f))</td><td
class="col1">The three values describe what depth foam starts to fade out, at what depth it is completely invisible, at what height foam for waves appears (+ waterHeight).</td><td
class="col2">Vector3f(0.45f,4.35f,1.0f)</td></tr><tr
class="row4"><td
class="col0">water.setFoamTexture( (Texture2D) <br/> manager.loadTexture(&quot;Textures/foam.png&quot;) )</td><td
class="col1">This foam texture will be used with WrapMode.Repeat</td><td
class="col2">&quot;Common/MatDefs/Water/Textures/foam.jpg&quot;</td></tr></table></div><div
class="table sectionedit5"><table
class="inline"><tr
class="row0"><th
class="col0"> Water method example</th><th
class="col1"> Effects: Light</th><th
class="col2">Default</th></tr><tr
class="row1"><td
class="col0">water.setSunScale(1f);</td><td
class="col1">Sets how big the sun should appear in the light&#039;s specular effect on the water.</td><td
class="col2">3.0f</td></tr><tr
class="row2"><td
class="col0">water.setUseSpecular(false)</td><td
class="col1">Switches specular effect on or off</td><td
class="col2">true</td></tr><tr
class="row3"><td
class="col0">water.setShininess(0.8f)</td><td
class="col1">Sets the shininess of the water reflections</td><td
class="col2">0.7f</td></tr><tr
class="row4"><td
class="col0">water.setUseRefraction(true)</td><td
class="col1">Switches the refraction effect on or off.</td><td
class="col2">true</td></tr><tr
class="row5"><td
class="col0">water.setRefractionConstant(0.2f);</td><td
class="col1">The lower the value, the less reflection can be seen on water. This is a constant related to the index of refraction (IOR) used to compute the fresnel term.</td><td
class="col2">0.3f</td></tr><tr
class="row6"><td
class="col0">water.setRefractionStrength(-0.1)</td><td
class="col1">This value modifies the current Fresnel term. If you want to weaken reflections use bigger value. If you want to empasize them, use a value smaller than 0.</td><td
class="col2">0.0f</td></tr><tr
class="row7"><td
class="col0">water.setReflectionMapSize(256)</td><td
class="col1">Sets the size of the reflection map. The higher, the better the quality, but the slower the effect.</td><td
class="col2">512</td></tr></table></div></div><h3><a
name="sound_effects">Sound Effects</a></h3><div
class="level3"><p> You should also add audio nodes with water sounds to complete the effect.</p><pre>AudioNode waves = new AudioNode&#40;assetManager, &quot;Sound/Environment/Ocean Waves.ogg&quot;, false&#41;;
&#125;</pre>
</div>
<h3><a>Optional: Water Wave and Color Effects</a></h3>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/water-post-muddy.png">
</p>
<p>
All these effects are optional. Every setter also has a getter.
</p>
<div><table>
<tr>
<th> Water method example</th><th>Effects: Waves </th><th>Default</th>
</tr>
<tr>
<td>water.setWaterHeight(-6);</td><td>Use this waterheight method for causing waves.</td><td>0.0f</td>
</tr>
<tr>
<td>water.setMaxAmplitude(0.3f);</td><td>How high the highest waves are.</td><td>1.0f</td>
</tr>
<tr>
<td>water.setWaveScale(0.008f);</td><td>Sets the scale factor of the waves height map. The smaller the value, the bigger the waves!</td><td> 0.005f </td>
</tr>
<tr>
<td>water.setWindDirection(new Vector2f(0,1))</td><td>Sets the wind direction, which is the direction where the waves move</td><td>Vector2f(0.0f, -1.0f)</td>
</tr>
<tr>
<td>water.setSpeed(0.7f);</td><td>How fast the waves move. Set it to 0.0f for still water.</td><td>1.0f</td>
</tr>
<tr>
<td>water.setHeightTexture( (Texture2D) <br/>
manager.loadTexture(&quot;Textures/waveheight.png&quot;) )</td><td>This height map describes the shape of the waves</td><td>&quot;Common/MatDefs/Water/Textures/heightmap.jpg&quot;</td>
</tr>
<tr>
<td>water.setNormalTexture( (Texture2D) <br/>
manager.loadTexture(&quot;Textures/wavenormals.png&quot;) )</td><td>This normal map describes the shape of the waves</td><td>&quot;Common/MatDefs/Water/Textures/gradient_map.jpg&quot;</td>
</tr>
<tr>
<td>water.setUseRipples(false);</td><td>Switches the ripples effect on or off.</td><td>true</td>
</tr>
<tr>
<td>water.setNormalScale(0.5f)</td><td>Sets the normal scaling factors to apply to the normal map. The higher the value, the more small ripples will be visible on the waves.</td><td>1.0f</td>
</tr>
</table></div>
<!-- EDIT1 TABLE [4858-6022] --><div><table>
<tr>
<th> Water method example</th><th> Effects: Color</th><th>Default</th>
</tr>
<tr>
<td>water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f))</td><td>Usually you set this to the same as the light source&#039;s direction. Use this to set the light direction if the sun is moving.</td><td>Value given to WaterFilter() constructor.</td>
</tr>
<tr>
<td>water.setLightColor(ColorRGBA.White)</td><td>Usually you set this to the same as the light source&#039;s color.</td><td>RGBA.White</td>
</tr>
<tr>
<td>water.setWaterColor(ColorRGBA.Brown.mult(2.0f));</td><td>Sets the main water color.</td><td>greenish blue <br/>
Vector3f(0.0f,0.5f,0.5f,1.0f)</td>
</tr>
<tr>
<td>water.setDeepWaterColor(ColorRGBA.Brown);</td><td>Sets the deep water color.</td><td>dark blue <br/>
Vector3f(0.0f, 0.0f,0.2f,1.0f)</td>
</tr>
<tr>
<td>water.setWaterTransparency(0.2f);</td><td>Sets how fast colors fade out. use this to control how clear (e.g. 0.05f) or muddy (0.2f) water is.</td><td> 0.1f </td>
</tr>
<tr>
<td>water.setColorExtinction(new Vector3f(10f,20f,30f));</td><td>Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to &quot;muddy&quot; the water.</td><td>Vector3f(5f,20f,30f)</td>
</tr>
</table></div>
<!-- EDIT2 TABLE [6024-7028] --><div><table>
<tr>
<th> Water method example</th><th> Effects: Shore</th><th>Default</th>
</tr>
<tr>
<td>water.setShoreHardness(1.0f);</td><td>Sets how soft the transition between shore and water should be. High values mean a harder transition between shore and water.</td><td>0.1f</td>
</tr>
<tr>
<td>water.setUseHQShoreline(false);</td><td>Renders shoreline with better quality ?</td><td>true</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [7030-7319] --><div><table>
<tr>
<th> Water method example</th><th> Effects: Foam</th><th>Default</th>
</tr>
<tr>
<td>water.setUseFoam(false);</td><td>Switches the white foam on or off</td><td>true</td>
</tr>
<tr>
<td>water.setFoamHardness(0.5f)</td><td>Sets how much the foam will blend with the shore to avoid a hard edged water plane.</td><td>1.0f</td>
</tr>
<tr>
<td>water.setFoamExistence(new Vector3f(0.5f,5f,1.0f))</td><td>The three values describe what depth foam starts to fade out, at what depth it is completely invisible, at what height foam for waves appears (+ waterHeight).</td><td>Vector3f(0.45f,4.35f,1.0f)</td>
</tr>
<tr>
<td>water.setFoamTexture( (Texture2D) <br/>
manager.loadTexture(&quot;Textures/foam.png&quot;) )</td><td>This foam texture will be used with WrapMode.Repeat</td><td>&quot;Common/MatDefs/Water/Textures/foam.jpg&quot;</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [7321-7966] --><div><table>
<tr>
<th> Water method example</th><th> Effects: Light</th><th>Default</th>
</tr>
<tr>
<td>water.setSunScale(1f);</td><td>Sets how big the sun should appear in the light&#039;s specular effect on the water.</td><td>3.0f</td>
</tr>
<tr>
<td>water.setUseSpecular(false)</td><td>Switches specular effect on or off</td><td>true</td>
</tr>
<tr>
<td>water.setShininess(0.8f)</td><td>Sets the shininess of the water reflections</td><td>0.7f</td>
</tr>
<tr>
<td>water.setUseRefraction(true)</td><td>Switches the refraction effect on or off.</td><td>true</td>
</tr>
<tr>
<td>water.setRefractionConstant(0.2f);</td><td>The lower the value, the less reflection can be seen on water. This is a constant related to the index of refraction (IOR) used to compute the fresnel term.</td><td>0.3f</td>
</tr>
<tr>
<td>water.setRefractionStrength(-0.1)</td><td>This value modifies the current Fresnel term. If you want to weaken reflections use bigger value. If you want to empasize them, use a value smaller than 0.</td><td>0.0f</td>
</tr>
<tr>
<td>water.setReflectionMapSize(256)</td><td>Sets the size of the reflection map. The higher, the better the quality, but the slower the effect.</td><td>512</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [7968-8883] -->
</div>
<h3><a>Sound Effects</a></h3>
<div>
<p>
You should also add audio nodes with water sounds to complete the effect.
</p>
<pre>AudioNode waves = new AudioNode&#40;assetManager, &quot;Sound/Environment/Ocean Waves.ogg&quot;, false&#41;;
waves.setLooping&#40;true&#41;;
audioRenderer.playSource&#40;waves&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:post-processor_water?do=export_xhtmlbody">view online version</a></em></p>
audioRenderer.playSource&#40;waves&#41;;</pre>
<hr />
<p>
See also:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/#comment-609"><param name="text" value="<html><u>JME3&#039;s Water Post-Process Effect</u></html>"><param name="textColor" value="blue"></object> by Nehon</div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:post-processor_water?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@ -1,31 +1,62 @@
<h1><a
name="ragdoll_physics">Ragdoll Physics</a></h1><div
class="level1"><p> The jMonkeyEngine3 has built-in support for <a
href="http://jbullet.advel.cz">jBullet physics</a> via the <code>com.jme3.bullet</code> package. Physics are not only responsible for handing collisions, but they also make <a
href="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a> possible. One special example of physical joints are ragdoll physics, shown here.</p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestRagDoll.java">TestRagDoll.java</a> (Tip: Click to pull the ragdoll up)</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBoneRagdoll.java">TestBoneRagdoll.java</a> – This ragdoll replaces a rigged model of a character in the moment it is &quot;shot&quot; to simulate a collapsing person. (Also note DoF of the limbs.)</div></li></ul></div><h2><a
name="preparing_the_physics_game">Preparing the Physics Game</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Create a SimpleApplication with a <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a></div><ul><li
class="level2"><div
class="li"> This gives us a PhysicsSpace for PhysicControls</div></li></ul></li><li
class="level1"><div
class="li"> Add a physical floor (A box collision shape with mass zero)</div></li></ol></div><h2><a
name="creating_the_ragdoll">Creating the Ragdoll</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:ragdoll.png?id=jme3%3Aadvanced%3Aragdoll"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png?w=200&amp;h=150" class="mediaright" align="right" alt="" width="200" height="150" /></a> The ragdoll is a simple dummy that we build out of cylinder collision shapes. It has 11 limbs: shoulders, a body, and hips; plus 2 arms and 2 legs are made up of two limbs each. In your game, you replace the cylinders with your own limb models.</p></div><h3><a
name="limbs">Limbs</a></h3><div
class="level3"><p> Since we&#039;re just creating the ragdoll for this example, all the limbs have the same shape, and we can write a simple helper method to create them. The function returns a PhysicsNode with CollisionShape with the width, height, location, and rotation (vertical or horizontal) that we specify. We choose a CapsuleCollisionShape (a cylinder with rounded top and bottom) so the limbs collide smoothly against one another.</p><pre>private Node createLimb&#40;float width, float height, Vector3f location, boolean rotate&#41; &#123;
<h1><a>Ragdoll Physics</a></h1>
<div>
<p>
The jMonkeyEngine3 has built-in support for <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jbullet.advel.cz"><param name="text" value="<html><u>jBullet physics</u></html>"><param name="textColor" value="blue"></object> via the <code>com.jme3.bullet</code> package. Physics are not only responsible for handing collisions, but they also make <a href="/com/jme3/gde/core/docs/jme3/advanced/hinges_and_joints.html">hinges and joints</a> possible. One special example of physical joints are ragdoll physics, shown here.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/ragdoll.png">
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestRagDoll.java"><param name="text" value="<html><u>TestRagDoll.java</u></html>"><param name="textColor" value="blue"></object> (Tip: Click to pull the ragdoll up)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestBoneRagdoll.java"><param name="text" value="<html><u>TestBoneRagdoll.java</u></html>"><param name="textColor" value="blue"></object> – This ragdoll replaces a rigged model of a character in the moment it is &quot;shot&quot; to simulate a collapsing person. (Also note DoF of the limbs.)</div>
</li>
</ul>
</div>
<h2><a>Preparing the Physics Game</a></h2>
<div>
<ol>
<li><div> Create a SimpleApplication with a <a href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a></div>
<ul>
<li><div> This gives us a PhysicsSpace for PhysicControls</div>
</li>
</ul>
</li>
<li><div> Add a physical floor (A box collision shape with mass zero)</div>
</li>
</ol>
</div>
<h2><a>Creating the Ragdoll</a></h2>
<div>
<p>
A ragdoll is a simple &quot;person&quot; (dummy) that you build out of cylinder collision shapes. The ragdoll has 11 limbs: 1 for shoulders, 1 for the body, 1 for hips; plus 2 arms and 2 legs that are made up of two limbs each. In your game, you will likely replace the cylinders with your own (better looking) limb models. In this example here we just use simple cylinders.
</p>
</div>
<h3><a>Limbs</a></h3>
<div>
<p>
Since you&#039;re just creating the ragdoll for this example, all the limbs have the same shape, and you can write a simple helper method to create them. The function returns a PhysicsControl with CollisionShape with the width, height, location, and rotation (vertical or horizontal) that you specify. You choose a CapsuleCollisionShape (a cylinder with rounded top and bottom) so the limbs collide smoothly against one another.
</p>
<pre>private Node createLimb&#40;float width, float height, Vector3f location, boolean rotate&#41; &#123;
int axis = rotate ? PhysicsSpace.AXIS_X : PhysicsSpace.AXIS_Y;
CapsuleCollisionShape shape = new CapsuleCollisionShape&#40;width, height, axis&#41;;
Node node = new Node&#40;&quot;Limb&quot;&#41;;
@ -33,15 +64,22 @@ class="level3"><p> Since we&#039;re just creating the ragdoll for this example,
node.setLocalTranslation&#40;location&#41;;
node.addControl&#40;rigidBodyControl&#41;;
return node;
&#125;</pre><p> We use this helper method to initialize the 11 limbs. Look at the screenshot above for orientation.</p><ul><li
class="level1"><div
class="li"> All cylinders have the same diameter, 0.2f.</div></li><li
class="level1"><div
class="li"> We make the body and shoulders longer than the other limbs, 1.0f instead of 0.5f.</div></li><li
class="level1"><div
class="li"> We determine the coordinates for positioning the limbs to form a person.</div></li><li
class="level1"><div
class="li"> The shoulders and hips are <em>vertical</em> cylinders, this is why we set the rotation to true.</div></li></ul><pre>Node shoulders = createLimb&#40;0.2f, 1.0f, new Vector3f&#40; 0.00f, 1.5f, 0&#41;, true&#41;;
&#125;</pre>
<p>
You write a custom helper method to initialize the limbs. Look at the screenshot above for orientation.
</p>
<ul>
<li><div> All cylinders have the same diameter, 0.2f.</div>
</li>
<li><div> You make the body and shoulders longer than the other limbs, 1.0f instead of 0.5f.</div>
</li>
<li><div> You determine the coordinates for positioning the limbs to form a person.</div>
</li>
<li><div> The shoulders and hips are <em>vertical</em> cylinders, this is why we set the rotation to true.</div>
</li>
</ul>
<pre>Node shoulders = createLimb&#40;0.2f, 1.0f, new Vector3f&#40; 0.00f, 1.5f, 0&#41;, true&#41;;
Node uArmL = createLimb&#40;0.2f, 0.5f, new Vector3f&#40;-0.75f, 0.8f, 0&#41;, false&#41;;
Node uArmR = createLimb&#40;0.2f, 0.5f, new Vector3f&#40; 0.75f, 0.8f, 0&#41;, false&#41;;
Node lArmL = createLimb&#40;0.2f, 0.5f, new Vector3f&#40;-0.75f,-0.2f, 0&#41;, false&#41;;
@ -51,15 +89,27 @@ Node hips = createLimb&#40;0.2f, 0.5f, new Vector3f&#40; 0.00f,-0.5f, 0&#41
Node uLegL = createLimb&#40;0.2f, 0.5f, new Vector3f&#40;-0.25f,-1.2f, 0&#41;, false&#41;;
Node uLegR = createLimb&#40;0.2f, 0.5f, new Vector3f&#40; 0.25f,-1.2f, 0&#41;, false&#41;;
Node lLegL = createLimb&#40;0.2f, 0.5f, new Vector3f&#40;-0.25f,-2.2f, 0&#41;, false&#41;;
Node lLegR = createLimb&#40;0.2f, 0.5f, new Vector3f&#40; 0.25f,-2.2f, 0&#41;, false&#41;;</pre><p> We now have the outline of a person. But if we ran the application now, the individual limbs would fall down independently of one another – the ragdoll is still lacking joints.</p></div><h3><a
name="joints">Joints</a></h3><div
class="level3"><p> As before, we write a small helper method. This time its purpose is to quickly join two limbs A and B at the connection point that we specify.</p><ul><li
class="level1"><div
class="li"> We convert A&#039;s and B&#039;s connectionPoint vector from world coordinate space to local coordinate space.</div></li><li
class="level1"><div
class="li"> We use a ConeJoint, a special joint that approximates the degree of freedom that limbs typically have. The ConeJoint constructor requires the two nodes, and the two local pivot coordinates that we just determined.</div></li><li
class="level1"><div
class="li"> We set the joints limits to allow swinging, but not twisting.</div></li></ul><pre>private PhysicsJoint join&#40;Node A, Node B, Vector3f connectionPoint&#41; &#123;
Node lLegR = createLimb&#40;0.2f, 0.5f, new Vector3f&#40; 0.25f,-2.2f, 0&#41;, false&#41;;</pre>
<p>
You now have the outline of a person. But if you ran the application now, the individual limbs would fall down independently of one another – the ragdoll is still lacking joints.
</p>
</div>
<h3><a>Joints</a></h3>
<div>
<p>
As before, you write a small helper method. This time its purpose is to quickly join two limbs A and B at the connection point that we specify.
</p>
<ul>
<li><div> Convert A&#039;s and B&#039;s connectionPoint vector from world coordinate space to local coordinate space.</div>
</li>
<li><div> Use a ConeJoint, a special joint that approximates the degree of freedom that limbs typically have. The ConeJoint constructor requires the two nodes, and the two local pivot coordinates that we just determined.</div>
</li>
<li><div> Set the joints limits to allow swinging, but not twisting.<pre>private PhysicsJoint join&#40;Node A, Node B, Vector3f connectionPoint&#41; &#123;
Vector3f pivotA = A.worldToLocal&#40;connectionPoint, new Vector3f&#40;&#41;&#41;;
Vector3f pivotB = B.worldToLocal&#40;connectionPoint, new Vector3f&#40;&#41;&#41;;
ConeJoint joint = new ConeJoint&#40;A.getControl&#40;RigidBodyControl.class&#41;,
@ -67,7 +117,16 @@ class="li"> We set the joints limits to allow swinging, but not twisting.</div><
pivotA, pivotB&#41;;
joint.setLimit&#40;1f, 1f, 0&#41;;
return joint;
&#125;</pre><p> We use the helper method to connect all limbs with joints where they belong, at one end of the limb.</p><pre>join&#40;body, shoulders, new Vector3f&#40; 0.00f, 1.4f, 0&#41;&#41;;
&#125;</pre>
</div>
</li>
</ul>
<p>
Use the helper method to connect all limbs with joints where they belong, at one end of the limb.
</p>
<pre>join&#40;body, shoulders, new Vector3f&#40; 0.00f, 1.4f, 0&#41;&#41;;
join&#40;body, hips, new Vector3f&#40; 0.00f, -0.5f, 0&#41;&#41;;
join&#40;uArmL, shoulders, new Vector3f&#40;-0.75f, 1.4f, 0&#41;&#41;;
join&#40;uArmR, shoulders, new Vector3f&#40; 0.75f, 1.4f, 0&#41;&#41;;
@ -76,9 +135,22 @@ join&#40;uArmR, lArmR, new Vector3f&#40; 0.75f, 0.4f, 0&#41;&#41;;
join&#40;uLegL, hips, new Vector3f&#40;-0.25f, -0.5f, 0&#41;&#41;;
join&#40;uLegR, hips, new Vector3f&#40; 0.25f, -0.5f, 0&#41;&#41;;
join&#40;uLegL, lLegL, new Vector3f&#40;-0.25f, -1.7f, 0&#41;&#41;;
join&#40;uLegR, lLegR, new Vector3f&#40; 0.25f, -1.7f, 0&#41;&#41;;</pre><p> Now the ragdoll is connected. If we ran the app now, the doll would collapse, but the limbs would stay together.</p></div><h3><a
name="attaching_everything_to_the_scene">Attaching Everything to the Scene</a></h3><div
class="level3"><p> We create one (non-physical) Node named ragDoll, and attach all other nodes to it.</p><pre>ragDoll.attachChild&#40;shoulders&#41;;
join&#40;uLegR, lLegR, new Vector3f&#40; 0.25f, -1.7f, 0&#41;&#41;;</pre>
<p>
Now the ragdoll is connected. If you ran the app now, the doll would collapse, but the limbs would stay together.
</p>
</div>
<h3><a>Attaching Everything to the Scene</a></h3>
<div>
<p>
We create one (non-physical) Node named ragDoll, and attach all other nodes to it.
</p>
<pre>ragDoll.attachChild&#40;shoulders&#41;;
ragDoll.attachChild&#40;body&#41;;
ragDoll.attachChild&#40;hips&#41;;
ragDoll.attachChild&#40;uArmL&#41;;
@ -88,15 +160,49 @@ ragDoll.attachChild&#40;lArmR&#41;;
ragDoll.attachChild&#40;uLegL&#41;;
ragDoll.attachChild&#40;uLegR&#41;;
ragDoll.attachChild&#40;lLegL&#41;;
ragDoll.attachChild&#40;lLegR&#41;;</pre><p> To use the ragdoll in a scene, we attach its main node to the rootNode, and to the PhysicsSpace.</p><pre>rootNode.attachChild&#40;ragDoll&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.addAll&#40;ragDoll&#41;;</pre></div><h2><a
name="applying_forces">Applying Forces</a></h2><div
class="level2"><p> To pull the doll up, you could add an input handler that triggers the following action:</p><pre>Vector3f upforce = new Vector3f&#40;0, 200, 0&#41;;
shoulders.applyContinuousForce&#40;true, upforce&#41;;</pre><p> We can use the action to pick the doll up and put it back on its feet, or what ever. Read more about <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics#forcesmoving_physical_objects.html">Forces</a> here.</p></div><h2><a
name="detecting_collisions">Detecting Collisions</a></h2><div
class="level2"><p> Read the <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics#responding_to_a_physicscollisionevent.html">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions.</p></div><h2><a
name="best_practices">Best Practices</a></h2><div
class="level2"><p> If you are seeing weird behaviour in a ragdoll – such as exploding into pieces and then reassembling – check your collision shapes. Verify you did not position the limbs too close to one another when assmebling the ragdoll. You typically see physical nodes being ejected when their collision shapes intersect, which puts physics in an impossible state.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:ragdoll?do=export_xhtmlbody">view online version</a></em></p>
ragDoll.attachChild&#40;lLegR&#41;;</pre>
<p>
To use the ragdoll in a scene, we attach its main node to the rootNode, and to the PhysicsSpace.
</p>
<pre>rootNode.attachChild&#40;ragDoll&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.addAll&#40;ragDoll&#41;;</pre>
</div>
<h2><a>Applying Forces</a></h2>
<div>
<p>
To pull the doll up, you could add an input handler that triggers the following action:
</p>
<pre>Vector3f upforce = new Vector3f&#40;0, 200, 0&#41;;
shoulders.applyContinuousForce&#40;true, upforce&#41;;</pre>
<p>
We can use the action to pick the doll up and put it back on its feet, or what ever. Read more about <a href="/com/jme3/gde/core/docs/jme3/advanced/physics#forcesmoving_physical_objects.html">Forces</a> here.
</p>
</div>
<h2><a>Detecting Collisions</a></h2>
<div>
<p>
Read the <a href="/com/jme3/gde/core/docs/jme3/advanced/physics#responding_to_a_physicscollisionevent.html">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions. You can detect collisions between limbs or between limbs and the floor, and trigger game events.
</p>
</div>
<h2><a>Best Practices</a></h2>
<div>
<p>
If you experience weird behaviour in a ragdoll – such as exploding into pieces and then reassembling – check your collision shapes. Verify you did not position the limbs too close to one another when assmebling the ragdoll. You typically see physical nodes being ejected when their collision shapes intersect, which puts physics in an impossible state.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:ragdoll?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

@ -0,0 +1,29 @@
<h1><a>Read Graphic Card Capabilites</a></h1>
<div>
<p>
You can read the graphic card&#039;s capabilities using the <code>com.jme3.renderer.Caps</code> class:
</p>
<pre>Collection&lt;Caps&gt; caps = renderer.getCaps&#40;&#41;;
Logger.getLogger&#40;HelloWorld.class.getName&#40;&#41;&#41;.log&#40;Level.INFO, “Caps: &#123;0&#125;” + caps.toString&#40;&#41;&#41;; </pre>
<p>
Replace HelloWorld by the name of the class where you are using this line.
</p>
<p>
The result looks like the following example:
</p>
<pre>Caps: [FrameBuffer, FrameBufferMRT, FrameBufferMultisample,
OpenGL20, ARBprogram, GLSL100, GLSL110, GLSL120,
VertexTextureFetch, FloatTexture, TextureCompressionLATC]</pre>
<p>
This would tell you that this user&#039;s graphic card only supports OpenGL 2.0 and cannot handle newer OpenGL features.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:read_graphic_card_capabilites?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,53 @@
<h1><a>Remote-Controlling the Camera</a></h1>
<div>
</div>
<h2><a>Positioning the Camera</a></h2>
<div>
<p>
You can steer the camera using <a href="/com/jme3/gde/core/docs/jme3/advanced/cinematics.html">Cinematics</a>:
</p>
<ol>
<li><div> Create a Cinematic.</div>
</li>
<li><div> Create a CameraNode and bind the camera object to the Cinematic. Note that we also give the camera node a name in this step. <pre>CameraNode camNode = cinematic.bindCamera&#40;&quot;topView&quot;, cam&#41;;</pre>
</div>
</li>
<li><div> Position the camera node in its start location.</div>
</li>
<li><div> Use activateCamera() to give the control of the camera to this node. You now see the scene from this camera&#039;s point of view. For example to see through the camera node named &quot;topView&quot;, 6 seconds after the start of the cinematic, you&#039;d write <pre>cinematic.activateCamera&#40;6, &quot;topView&quot;&#41;;</pre>
</div>
</li>
</ol>
</div>
<h3><a>Code Sample</a></h3>
<div>
<pre>flyCam.setEnabled&#40;false&#41;;
Cinematic cinematic = new Cinematic&#40;rootNode, 20&#41;;
&nbsp;
CameraNode camNodeTop = cinematic.bindCamera&#40;&quot;topView&quot;, cam&#41;;
camNodeTop.setControlDir&#40;ControlDirection.SpatialToCamera&#41;;
camNodeTop.getControl&#40;0&#41;.setEnabled&#40;false&#41;;
&nbsp;
CameraNode camNodeSide = cinematic.bindCamera&#40;&quot;sideView&quot;, cam&#41;;
camNodeSide.setControlDir&#40;ControlDirection.CameraToSpatial&#41;;
camNodeSide.getControl&#40;0&#41;.setEnabled&#40;false&#41;;</pre>
</div>
<h2><a>Moving the Camera</a></h2>
<div>
<p>
If desired, attach the camNode to a MotionTrack to let it travel along waypoints. This is demonstrated in the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/animation/TestCinematic.java"><param name="text" value="<html><u>TestCameraMotionPath.java example</u></html>"><param name="textColor" value="blue"></object>.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:remote-controlling_the_camera?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,48 @@
<h1><a>Saving and Loading Games</a></h1>
<div>
<p>
You can save and load scenes and individual Nodes using com.jme3.export.binary.BinaryExporter and com.jme3.export.binary.BinaryImporter. Use standard Java serialization to load game data. The jMonkeyEngine binary file format is .j3o. You can open, view, and edit .j3o files in the jMonkeyPlatform.
</p>
</div>
<h2><a>Saving a Node</a></h2>
<div>
<pre> @Override
public void destroy&#40;&#41; &#123;
System.getProperty&#40;&quot;user.home&quot;&#41;;
BinaryExporter exporter = BinaryExporter.getInstance&#40;&#41;;
File&#40;userHome+&quot;/somefile.j3o&quot;&#41;;
try &#123;
exporter.save&#40;rootNode, file&#41;;
&#125; catch &#40;IOException ex&#41; &#123;
Logger.getLogger&#40;Main.class.getName&#40;&#41;&#41;.log&#40;Level.SEVERE, &quot;Failed to save node!&quot;, ex&#41;;
&#125;
super.destroy&#40;&#41;;
&#125;</pre>
</div>
<h2><a>Loading a Node</a></h2>
<div>
<pre> @Override
public void simpleInitApp&#40;&#41; &#123;
System.getProperty&#40;&quot;user.home&quot;&#41;;
BinaryImporter importer = BinaryImporter.getInstance&#40;&#41;;
importer.setAssetManager&#40;assetManager&#41;;
File&#40;userHome+&quot;/somefile.j3o&quot;&#41;;
try &#123;
Node loadedNode = &#40;Node&#41;importer.load&#40;file&#41;;
loadedNode.setName&#40;&quot;loaded node&quot;&#41;;
rootNode.attachChild&#40;loadedNode&#41;;
&#125; catch &#40;IOException ex&#41; &#123;
Logger.getLogger&#40;Main.class.getName&#40;&#41;&#41;.log&#40;Level.SEVERE, &quot;No saved node loaded.&quot;, ex&#41;;
&#125;
...
&nbsp;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:save_and_load?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@ -1,33 +1,147 @@
<h1><a
name="shapes">Shapes</a></h1><div
class="level1"><p> The simplest type of Meshes are jME&#039;s default Shapes. You can use Shapes to build complex Geometries. Shapes are created without using the AssetManager.</p><p> <strong>3D shapes:</strong></p><ul><li
class="level1"><div
class="li"> com.jme3.scene.shape.Sphere – A ball or elipsoid.</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.Box – A cube or cuboid.</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.Cylinder – A disk or pillar.</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.Dome – Half a sphere.</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.Torus – An single-holed torus (&quot;donut&quot;).</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.PQTorus – A parameterized torus, also known as PQ torus. Looks like a <a
href="http://en.wikipedia.org/wiki/Torus_knot">donut knotted into spirals</a>.</div></li></ul><p> <strong>Non-3D shapes:</strong></p><ul><li
class="level1"><div
class="li"> com.jme3.scene.shape.Quad – A flat 2D rectangle (has two sides)</div></li><li
class="level1"><div
class="li"> com.jme3.scene.shape.Line – A 1D line (has a length)</div></li><li
class="level1"><div
class="li"> come.jme3.math.Ray – A 1D line (has length, direction, start point, but no end)</div></li></ul></div><h2><a
name="usage">Usage</a></h2><div
class="level2"><p> To add a shape to the scene:</p><ol><li
class="level1"><div
class="li"> Create the base mesh shape</div></li><li
class="level1"><div
class="li"> Wrap it into a Geometry</div></li><li
class="level1"><div
class="li"> Attach the Geometry to the rootNode to make it visible.</div></li></ol><pre>Sphere sphereMesh = new Sphere&#40;32, 32, 10, false, true&#41;;
Geometry sphere = new Geometry&#40;&quot;Sky&quot;, sphereMesh&#41;;
rootNode.attachChild&#40;sphere&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:shape?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Shapes</a></h1>
<div>
<p>
The simplest type of Meshes are the built-in JME Shapes. You can create Shapes without using the AssetManager.
</p>
</div>
<h2><a>List of 3D shapes</a></h2>
<div>
<ul>
<li><div> com.jme3.scene.shape.Box – A cube or cuboid. Single-sided Quad faces (outside only). </div>
</li>
<li><div> com.jme3.scene.shape.StripBox – A cube or cuboid. Solid filled faces (inside and outside).</div>
</li>
<li><div> com.jme3.scene.shape.Cylinder – A disk or pillar.</div>
</li>
<li><div> com.jme3.scene.shape.Sphere – A ball or elipsoid.</div>
</li>
<li><div> com.jme3.scene.shape.Dome – Semi-sphere, e.g. SkyDome. </div>
</li>
<li><div> com.jme3.scene.shape.Torus – An single-holed torus or &quot;donut&quot;.</div>
</li>
<li><div> com.jme3.scene.shape.PQTorus – A parameterized torus. A PQ-Torus looks like a <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/Torus_knot"><param name="text" value="<html><u>donut knotted into spirals</u></html>"><param name="textColor" value="blue"></object>.</div>
</li>
<li><div> com.jme3.scene.shape.Surface – A curved surface (called <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikipedia.org/wiki/File:NURBS_3-D_surface.gif"><param name="text" value="<html><u>NURBS</u></html>"><param name="textColor" value="blue"></object>) described by knots, weights and control points. Compare with shape.Curve.</div>
</li>
</ul>
</div>
<h2><a>List of Non-3D shapes</a></h2>
<div>
<ul>
<li><div> com.jme3.scene.shape.Quad – A flat 2D rectangle (has two sides)</div>
</li>
<li><div> com.jme3.scene.shape.Line – A straight 1D line defined by a start and end point.</div>
</li>
<li><div> com.jme3.scene.shape.Curve – A curved 1D spline. Compare with shape.Surface.</div>
</li>
</ul>
</div>
<h3><a>Math versus Shape?</a></h3>
<div>
<p>
Do not mix up these visible Shapes with similarly named classes from the maths package. Choose the right package when letting your IDE fill in the import statements!
</p>
<ul>
<li><div> com.jme3.math.Line – is invisible, has a direction, goes through a point, infinite length.</div>
</li>
<li><div> com.jme3.math.Ray – is invisible, has a direction and start point, but no end.</div>
</li>
<li><div> com.jme3.math.Spline – is an invisible curve.</div>
</li>
<li><div> etc</div>
</li>
</ul>
<p>
These maths objects are invisible and are used for collision testing (ray casting) or to describe motion paths. They cannot be wrapped into a Geometry.
</p>
</div>
<h2><a>Usage</a></h2>
<div>
</div>
<h3><a>Basic Usage</a></h3>
<div>
<p>
To add a shape to the scene:
</p>
<ol>
<li><div> Create the base mesh shape.</div>
</li>
<li><div> Wrap it into a Geometry.</div>
</li>
<li><div> Assign a Material to the Geometry.</div>
</li>
<li><div> Attach the Geometry to the rootNode to make it visible.</div>
</li>
</ol>
</div>
<h3><a>Complex Shapes</a></h3>
<div>
<p>
You can compose more complex custom Geometries out of simple Shapes. Think of the buildings in games like Angry Birds, or the building blocks in Second Life (&quot;prims&quot;) and in Tetris (&quot;Tetrominos&quot;).
</p>
<ol>
<li><div> Create a Node. By default it is located at the origin (0/0/0) – leave the Node there for now.</div>
</li>
<li><div> Create your shapes and wrap each into a Geometry, as just described.</div>
</li>
<li><div> Attach each Geometry to the Node.</div>
</li>
<li><div> Arrange the Geometries around the Node (using <code>setLocalTranslation()</code>) so that the Node is in the center of the new constellation. The central Node is the pivot point for transformations (move/scale/rotate).</div>
</li>
<li><div> Move the pivot Node to its final location in the scene. Moving the pivot Node moves the attached constellation of Geometries with it.</div>
</li>
</ol>
<p>
The order is important: First arrange around origin, then transform. Otherwise, transformations are applied around the wrong center (pivot). Of course, you can attach your constellation to other pivot Nodes to create even more complex shapes (a chair, a furnished room, a house, a city, …), but again, arrange them around the origin first before you transform them.
<br/>
Note: Obviously, these composed Geometries are simpler than hand-sculpted meshes from a mesh editor.
</p>
</div>
<h2><a>Code Examples</a></h2>
<div>
<pre>Sphere mesh = new Sphere&#40;32, 32, 10, false, true&#41;;</pre>
<pre>Dome mesh = new Dome&#40;Vector3f.ZERO, 2, 4, 1f,false&#41;; // Pyramid</pre>
<pre>Dome mesh = new Dome&#40;Vector3f.ZERO, 2, 32, 1f,false&#41;; // Cone</pre>
<pre>Dome mesh = new Dome&#40;Vector3f.ZERO, 32, 32, 1f,false&#41;; // Small hemisphere</pre>
<pre>Dome mesh = new Dome&#40;Vector3f.ZERO, 32, 32, 1000f,true&#41;; // SkyDome</pre>
<pre>PQTorus mesh = new PQTorus&#40;5,3, 2f, 1f, 32, 32&#41;; // Spiral torus</pre>
<pre>PQTorus mesh = new PQTorus&#40;3,8, 2f, 1f, 32, 32&#41;; // Flower torus</pre>
<p>
Use one of the above examples together with the following geometry in a scene:
</p>
<pre>Geometry geom = new Geometry&#40;&quot;A shape&quot;, mesh&#41;;
Material mat = new Material&#40;assetManager,
&quot;Common/MatDefs/Misc/ShowNormals.j3md&quot;&#41;;
geom.setMaterial&#40;mat&#41;;
rootNode.attachChild&#40;geom&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:shape?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 57 KiB

@ -1,42 +1,101 @@
<h1><a
name="how_to_add_a_sky_to_your_scene">How to add a Sky to your Scene</a></h1><div
class="level1"><p> <br/></p><p> Here is an example for how you add a static horizon (a background landscape and a sky) to a scene.
Having a discernable horizon with a suitable landscape (or space, or ocean, or whatever) in the background makes scenes look more realistic than just a single-colored &quot;sky&quot; background.</p></div><h2><a
name="adding_the_sky">Adding the Sky</a></h2><div
class="level2"><p> Adding a sky is extremely easy using the <code>com.jme3.util.SkyFactory</code>.</p><pre>rootNode.attachChild&#40;SkyFactory.createSky&#40;
assetManager, &quot;Textures/Sky/Bright/BrightSky.dds&quot;, false&#41;&#41;;</pre><p> To add a sky you need to supply:</p><ol><li
class="level1"><div
class="li"> The assetManager object to use</div></li><li
class="level1"><div
class="li"> A cube or sphere map texture of the sky</div></li><li
class="level1"><div
class="li"> Set the boolean to true if you are using a sphere map texture. For a cube map, use false. <br/> Tip: Cube map is the default. You would know if you had created a sphere map.</div></li></ol><p> Internally, the SkyFactory calls the following methods:</p><ol><li
class="level1"><div
class="li"> <code>sky.setQueueBucket(Bucket.Sky);</code> makes certain the sky is rendered in the right order, behind everything else.</div></li><li
class="level1"><div
class="li"> <code>sky.setCullHint(Spatial.CullHint.Never);</code> makes certain that the sky is never culled.</div></li><li
class="level1"><div
class="li"> The SkyFactory uses the internal jME3 material definition <code>Sky.j3md</code>. This Material definition works with sphere and cube maps.</div></li></ol></div><h2><a
name="creating_the_textures">Creating the Textures</a></h2><div
class="level2"><p> As the sky texture we use the sample BrightSky.dds file from jme3test-test-data.</p><p> How to create a sky textures?</p><ul><li
class="level1"><div
class="li"> There are many tools out there that generate cube and sphere maps. <br/> Examples for landscape texture generators are Terragen or Bryce.</div></li><li
class="level1"><div
class="li"> The actual texture size does not matter, as long as you add the Sky Geometry to the Sky bucket: Everything in the sky bucket will always be infinitely far away behind everything else, and never intersect with your scene. <br/> Of course the higher the resolution, the better it will look. On the other hand, if the graphic is too big, it will slow the game down.</div></li><li
class="level1"><div
class="li"> A box or sphere map is the simplest solution. But you can use any Node as sky, even complex sets of geometries and quads with animated clouds, blinking stars, city skylines, etc.</div></li><li
class="level1"><div
class="li"> JME3 supports cube maps in <acronym
title="Portable Network Graphics">PNG</acronym>, <acronym
title="Joint Photographics Experts Group">JPG</acronym>, or (compressed) DDS format.</div></li></ul><p> Box or Sphere?</p><ul><li
class="level1"><div
class="li"> If you have access to cube map textures, then use a SkyBox</div><ul><li
class="level2"><div
class="li"> <a
href="http://1.bp.blogspot.com/_uVsWqMqIGQU/SN0IZEE117I/AAAAAAAAAPs/4lfHx1Erdqg/s1600/skybox">SkyBox examples</a></div></li></ul></li><li
class="level1"><div
class="li"> If you have access to sphere map textures – specially projected sky images that fit inside a sphere – then you use a SkySphere or SkyDome.</div><ul><li
class="level2"><div
class="li"> <a
href="http://wiki.delphigl.com/index.php/Datei:Skysphere.jpg">SkySphere example</a></div></li></ul></li></ul></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:sky?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>How to add a Sky to your Scene</a></h1>
<div>
<p>
<br/>
</p>
<p>
Here is an example for how you add a static horizon (a background landscape and a sky) to a scene.
Having a discernable horizon with a suitable landscape (or space, or ocean, or whatever) in the background makes scenes look more realistic than just a single-colored &quot;sky&quot; background.
</p>
</div>
<h2><a>Adding the Sky</a></h2>
<div>
<p>
Adding a sky is extremely easy using the <code>com.jme3.util.SkyFactory</code>.
</p>
<pre>rootNode.attachChild&#40;SkyFactory.createSky&#40;
assetManager, &quot;Textures/Sky/Bright/BrightSky.dds&quot;, false&#41;&#41;;</pre>
<p>
To add a sky you need to supply:
</p>
<ol>
<li><div> The assetManager object to use</div>
</li>
<li><div> A cube or sphere map texture of the sky</div>
</li>
<li><div> Set the boolean to true if you are using a sphere map texture. For a cube map, use false. <br/>
Tip: Cube map is the default. You would know if you had created a sphere map.</div>
</li>
</ol>
<p>
Internally, the SkyFactory calls the following methods:
</p>
<ol>
<li><div> <code>sky.setQueueBucket(Bucket.Sky);</code> makes certain the sky is rendered in the right order, behind everything else.</div>
</li>
<li><div> <code>sky.setCullHint(Spatial.CullHint.Never);</code> makes certain that the sky is never culled.</div>
</li>
<li><div> The SkyFactory uses the internal jME3 material definition <code>Sky.j3md</code>. This Material definition works with sphere and cube maps. </div>
</li>
</ol>
</div>
<h2><a>Creating the Textures</a></h2>
<div>
<p>
As the sky texture we use the sample BrightSky.dds file from jme3test-test-data.
</p>
<p>
How to create a sky textures?
</p>
<ul>
<li><div> There are many tools out there that generate cube and sphere maps. <br/>
Examples for landscape texture generators are Terragen or Bryce.</div>
</li>
<li><div> The actual texture size does not matter, as long as you add the Sky Geometry to the Sky bucket: Everything in the sky bucket will always be infinitely far away behind everything else, and never intersect with your scene. <br/>
Of course the higher the resolution, the better it will look. On the other hand, if the graphic is too big, it will slow the game down. </div>
</li>
<li><div> A box or sphere map is the simplest solution. But you can use any Node as sky, even complex sets of geometries and quads with animated clouds, blinking stars, city skylines, etc.</div>
</li>
<li><div> JME3 supports cube maps in <acronym title="Portable Network Graphics">PNG</acronym>, <acronym title="Joint Photographics Experts Group">JPG</acronym>, or (compressed) DDS format.</div>
</li>
</ul>
<p>
Box or Sphere?
</p>
<ul>
<li><div> If you have access to cube map textures, then use a SkyBox</div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://1.bp.blogspot.com/_uVsWqMqIGQU/SN0IZEE117I/AAAAAAAAAPs/4lfHx1Erdqg/s1600/skybox"><param name="text" value="<html><u>SkyBox examples</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
<li><div> If you have access to sphere map textures – specially projected sky images that fit inside a sphere – then you use a SkySphere or SkyDome. </div>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://wiki.delphigl.com/index.php/Datei:Skysphere.jpg"><param name="text" value="<html><u>SkySphere example</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:sky?do=export_xhtmlbody">view online version</a></em></p>

@ -1,59 +1,138 @@
<h1><a
name="spatial">Spatial</a></h1><div
class="level1"><p> This is an introduction to the concept of of Spatials, the elements of the 3D scene graph. The scene graph is a data structure that manages all objects in your 3D world. For example it keeps track of the 3D models that you load and position. When you extend a Java class from com.jme3.app.SimpleApplication, you inherit the scene graph and rootNode.</p><p> The main element of the scene graph is a Spatial called rootNode. All other Spatials are <em>attached</em> to the rootNode in a parent-child relationship. If you think you want to understand the scene graph better, please read <a
href="/com/jme3/gde/core/docs/jme3/scenegraph_for_dummies.html">Scenegraph for dummies</a> first.</p></div><h2><a
name="node_versus_geometry">Node versus Geometry</a></h2><div
class="level2"><p> A Spatial is either a Node or a Geometry.</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:intermediate:scene-graph.png?id=jme3%3Aadvanced%3Aspatial"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/intermediate/scene-graph.png" class="mediacenter" alt="" /></a></p><div
class="table sectionedit1"><table
class="inline"><tr
class="row0"><td
class="col0 leftalign"></td><th
class="col1" colspan="2"> Spatials</th></tr><tr
class="row1"><th
class="col0"> Purpose:</th><td
class="col1" colspan="2"> A Spatial is an abstract data structure that stores transformations (translation, rotation, scale) of elements of the scene graph. A Spatial can be saved and loaded using the AssetManager.</td></tr><tr
class="row2"><td
class="col0 leftalign"></td><th
class="col1"> com.jme3.scene.Geometry</th><th
class="col2"> com.jme3.scene.Node</th></tr><tr
class="row3"><th
class="col0"> Visibility:</th><td
class="col1"> A Geometry represents a visible 3-D object in the scene graph.</td><td
class="col2"> A Node is an invisible &quot;handle&quot; for a group of objects in the scene graph.</td></tr><tr
class="row4"><th
class="col0 leftalign"> Purpose:</th><td
class="col1"> Use Geometries to represent an object&#039;s looks: Every Geometry contains a polygon mesh and a material, specifying its shape, color, texture, and opacity/transparency. <br/> You can attach a Geometry to an Node.</td><td
class="col2"> Use nodes to structure and group Geometries and other Nodes. Every Node is attached to parent node, and the node can have children attached to itself. When you transform a parent node, all its children are transformed as well.</td></tr><tr
class="row5"><th
class="col0 leftalign"> Content:</th><td
class="col1"> Transformations, mesh, material.</td><td
class="col2"> Transformations. No mesh, no material.</td></tr><tr
class="row6"><th
class="col0 leftalign"> Examples:</th><td
class="col1"> A box, a sphere, player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc…</td><td
class="col2"> The rootNode, the guiNode, an audio node, a custom grouping node, etc…</td></tr></table></div><p> <strong>Important:</strong> You never create a Spatial with <code>Spatial s = new Spatial();</code> – it&#039;s abstract. Instead you create (e.g. load) a Node or Geometry object, and cast it to Spatial. You use the Spatial type in methods that accept both Nodes and Geometries as arguments.</p></div><h3><a
name="mesh">Mesh</a></h3><div
class="level3"><p> The polygon <a
href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a> inside a Geometry can be one of three things:</p><ul><li
class="level1"><div
class="li"> <strong>Shapes:</strong> The simplest type of Meshes are jME&#039;s default <a
href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s such as cubes and spheres. You can use several Shapes to build complex Geometries. Shapes are built-in and can be created without using the AssetManager.</div></li><li
class="level1"><div
class="li"> <strong>3D Models:</strong> <a
href="/com/jme3/gde/core/docs/jme3/advanced/3d_models.html">3D models and scenes</a> are also made up of meshes, but are more complex than Shapes. You create Models and Scenes in external 3D Mesh Editors and export them as Ogre <acronym
title="Extensible Markup Language">XML</acronym> or Wavefront OBJ. Use the <a
href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models into a your jME3 game.</div></li><li
class="level1"><div
class="li"> <strong>Custom Meshes:</strong> Advanced users can create <a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html">Custom Meshes</a> programmatically.</div></li></ul></div><h2><a
name="how_to_access_a_named_sub-mesh">How to Access a Named Sub-Mesh</a></h2><div
class="level2"><p> Often after you load a scene or model, you need to access a part of it as an individual Geometry in the scene graph. Maybe you want to swap a character&#039;s weapon, or you want to play a door-opening animation. First you need to know the unique name of the sub-mesh.</p><ol><li
class="level1"><div
class="li"> Open the model in a 3D mesh editor, or in the jMonkeyPlatform&#039;s viewer.</div></li><li
class="level1"><div
class="li"> Find out the existing names of sub-meshes in the model.</div></li><li
class="level1"><div
class="li"> Assign unique names to sub-meshes in the model if neccessary.</div></li></ol><p> In the following example, the Node <code>house</code> is the loaded model. The sub-meshes in the Node are called its children. The String, here <code>door 12</code>, is the name of the mesh that you are searching.</p><pre>Geometry submesh = &#40;Geometry&#41; houseScene.getChild&#40;&quot;door 12&quot;&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:spatial?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Spatial</a></h1>
<div>
<p>
This is an introduction to the concept of Spatials, the elements of the 3D scene graph. The scene graph is a data structure that manages all objects in your 3D world. For example, the scene graph keeps track of the 3D models that you load and position. When you extend a Java class from com.jme3.app.SimpleApplication, you automatically inherit the scene graph and its rootNode.
</p>
<p>
The rootNode is the central element of the scene graph. Even if the scenegraph is empty, it always has at least its rootNode. All other Spatials are <em>attached</em> to the rootNode in a parent-child relationship. If you think you need to understand the scene graph concept better, please read <a href="/com/jme3/gde/core/docs/jme3/scenegraph_for_dummies.html">Scenegraph for dummies</a> first.
</p>
</div>
<h2><a>Node versus Geometry</a></h2>
<div>
<p>
In your Java code, a Spatial is either a com.jme3.scene.Node or a com.jme3.scene.Geometry. You use the two for different purposes:
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/intermediate/scene-graph.png">
</p>
<div><table>
<tr>
<td> </td><th>com.jme3.scene.Spatial </th>
</tr>
<tr>
<th> Purpose: </th><td> A Spatial is an abstract data structure that stores transformations (translation, rotation, scale) of elements of the scene graph. Spatials can be saved and loaded using the AssetManager. </td>
</tr>
<tr>
<td> </td><th> com.jme3.scene.Geometry </th><th> com.jme3.scene.Node </th>
</tr>
<tr>
<th> Visibility: </th><td> A Geometry represents a visible 3-D object in the scene graph. </td><td> A Node is an invisible &quot;handle&quot; for a group of objects in the scene graph. </td>
</tr>
<tr>
<th> Purpose: </th><td> Use Geometries to represent an object&#039;s looks: Every Geometry contains a polygon mesh and a material, specifying its shape, color, texture, and opacity/transparency. <br/>
You can attach a Geometry to a Node. </td><td> Use Nodes to structure and group Geometries and other Nodes. Every Node is attached to one parent node, and each node can have zero or more children attached to itself. When you transform a parent node, all its children are transformed as well. </td>
</tr>
<tr>
<th> Content: </th><td> Transformations; custom user data; <br/>
mesh, material; </td><td> Transformations; custom user data; <br/>
no mesh, no material.</td>
</tr>
<tr>
<th> Examples: </th><td> A box, a sphere, player, a building, a piece of terrain, a vehicle, missiles, NPCs, etc… </td><td> The rootNode, the guiNode, an audio node, a custom grouping node, etc… </td>
</tr>
</table></div>
<!-- EDIT1 TABLE [944-2177] -->
<p>
<p><div>You never create a Spatial with <code>Spatial s = new Spatial();</code>! A Spatial is an abstract concept, like a mammal (there is no actual creature called &quot;mammal&quot; walking around here). You create a Node, or load a Geometry object. Some methods however require a Spatial argement: This is because they are able to accept both Nodes and Geometries as arguments. In this case, you must cast a Node or Geometry to Spatial.
</div></p>
</p>
</div>
<h3><a>Mesh</a></h3>
<div>
<p>
The polygon <a href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a> inside a Geometry can be one of three things:
</p>
<ul>
<li><div> <strong>Shapes:</strong> The simplest type of Meshes are jME&#039;s default <a href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s such as cubes and spheres. You can use several Shapes to build complex Geometries. Shapes are built-in and can be created without using the AssetManager.</div>
</li>
<li><div> <strong>3D Models:</strong> <a href="/com/jme3/gde/core/docs/jme3/advanced/3d_models.html">3D models and scenes</a> are also made up of meshes, but are more complex than Shapes. You create Models and Scenes in external 3D Mesh Editors and export them as Ogre <acronym title="Extensible Markup Language">XML</acronym> or Wavefront OBJ. Use the <a href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models into a your jME3 game.</div>
</li>
<li><div> <strong>Custom Meshes:</strong> Advanced users can create <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html">Custom Meshes</a> programmatically.</div>
</li>
</ul>
</div>
<h2><a>How to Add User Data to a Spatial</a></h2>
<div>
<p>
You can include custom Java objects in Nodes and Geometries. This is useful for maintaining information about a game element, such as health, budget, ammunition, inventory, equipment, etc for players, or landmark locations for terrains, and much more. Where ever the spatial is accessible, you can also access the object&#039;s game data.
</p>
<pre>// create and instance of your custom data class
PlayerData playerData = new PlayerData&#40;&quot;joe&quot;, 0, 100&#41;;
// store custom data in Node or Geometry
player.setUserData&#40;&quot;player data&quot;, playerData&#41;;
...
// Elsewhere: retrieved data from Node or Geometry...
PlayerData playerData = player.getUserData&#40;&quot;player data&quot;&#41;;
// ... set the data...
playerData.setHealth&#40;&quot;99&quot;&#41;;
// ... or get the data for tests or to display it in the HUD.
health = playerData.getHealth&#40;&#41;;</pre>
<p>
You can add as many data objects to a Spatial as you need. Just make sure to label them with different Strings (<code>player data</code>, <code>player inventory</code>, <code>player equipment</code>, etc).
</p>
<p>
You can also list all data keys that are defined for one Spatial:
</p>
<pre>for&#40;String key : geom.getUserDataKeys&#40;&#41;&#41;&#123;
System.out.println&#40;geom.getName&#40;&#41;+&quot;'s keys: &quot;+key&#41;;
&#125;</pre>
</div>
<h2><a>How to Access a Named Sub-Mesh</a></h2>
<div>
<p>
Often after you load a scene or model, you need to access a part of it as an individual Geometry in the scene graph. Maybe you want to swap a character&#039;s weapon, or you want to play a door-opening animation. First you need to know the unique name of the sub-mesh.
</p>
<ol>
<li><div> Open the model in a 3D mesh editor, or in the jMonkeyPlatform&#039;s viewer. </div>
</li>
<li><div> Find out the existing names of sub-meshes in the model.</div>
</li>
<li><div> Assign unique names to sub-meshes in the model if neccessary.</div>
</li>
</ol>
<p>
In the following example, the Node <code>house</code> is the loaded model. The sub-meshes in the Node are called its children. The String, here <code>door 12</code>, is the name of the mesh that you are searching.
</p>
<pre>Geometry submesh = &#40;Geometry&#41; houseScene.getChild&#40;&quot;door 12&quot;&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:spatial?do=export_xhtmlbody">view online version</a></em></p>

@ -1,60 +1,180 @@
<h1><a
name="jme3_canvas_in_a_swing_gui">JME3 Canvas in a Swing GUI</a></h1><div
class="level1"><p> 3D games are typically played full-screen, or in a window that takes over the mouse and all inputs. However it is also possible to embed a jME 3 canvas in a standard Swing application. <br/> <br/> This can be useful when you create some sort of interactive 3D viewer with a user interface that is more complex than just a HUD: For instance an interactive scientific demo, a level editor, or a game character designer. <br/> <br/></p><ul><li
class="level1"><div
class="li"> Advantages:</div><ul><li
class="level2"><div
class="li"> You can use Swing components (frame, panels, menus, controls) next to your jME3 game.</div></li><li
class="level2"><div
class="li"> The NetBeans <acronym
title="Graphical User Interface">GUI</acronym> builder is compatible with the jMonkeyEngine; you can use it it to lay out the Swing <acronym
title="Graphical User Interface">GUI</acronym> frame, and then add() the jME canvas into it. Install the <acronym
title="Graphical User Interface">GUI</acronym> builder via Tools → Plugins → Available Plugins.</div></li></ul></li><li
class="level1"><div
class="li"> Disadvantages:</div><ul><li
class="level2"><div
class="li"> You cannot use SimpleApplication&#039;s default mouse capturing for camera navigation, but have to come up with a custom solution.</div></li></ul></li></ul><p> Here is the full <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/awt/TestCanvas.java">TestCanvas.java</a> code sample.</p></div><h2><a
name="extending_simpleapplication">Extending SimpleApplication</a></h2><div
class="level2"><p> You start out just the same as for any jME3 game: The base application, here SwingCanvasTest, extends <code>com.jme3.app.SimpleApplication</code>. As usual, you use <code>simpleInitApp()</code> to initialize the scene, and <code>simpleUpdate()</code> as event loop. <br/> <br/> The camera&#039;s default behaviour in SimpleApplication is to capture the mouse, which doesn&#039;t make sense in a Swing window. You have to deactivate and replace this behaviour by <code>flyCam.setDragToRotate(true);</code> when you initialize the application:</p><pre>public void simpleInitApp&#40;&#41; &#123;
<h1><a>JME3 Canvas in a Swing GUI</a></h1>
<div>
<p>
3D games are typically played full-screen, or in a window that takes over the mouse and all inputs. However it is also possible to embed a jME 3 canvas in a standard Swing application. <br/>
<br/>
This can be useful when you create some sort of interactive 3D viewer with a user interface that is more complex than just a HUD: For instance an interactive scientific demo, a level editor, or a game character designer. <br/>
<br/>
</p>
<ul>
<li><div> Advantages:</div>
<ul>
<li><div> You can use Swing components (frame, panels, menus, controls) next to your jME3 game.</div>
</li>
<li><div> The NetBeans <acronym title="Graphical User Interface">GUI</acronym> builder is compatible with the jMonkeyEngine; you can use it it to lay out the Swing <acronym title="Graphical User Interface">GUI</acronym> frame, and then add() the jME canvas into it. Install the <acronym title="Graphical User Interface">GUI</acronym> builder via Tools → Plugins → Available Plugins.</div>
</li>
</ul>
</li>
<li><div> Disadvantages:</div>
<ul>
<li><div> You cannot use SimpleApplication&#039;s default mouse capturing for camera navigation, but have to come up with a custom solution.</div>
</li>
</ul>
</li>
</ul>
<p>
Here is the full <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/awt/TestCanvas.java"><param name="text" value="<html><u>TestCanvas.java</u></html>"><param name="textColor" value="blue"></object> code sample.
</p>
</div>
<h2><a>Extending SimpleApplication</a></h2>
<div>
<p>
You start out just the same as for any jME3 game: The base application, here SwingCanvasTest, extends <code>com.jme3.app.SimpleApplication</code>. As usual, you use <code>simpleInitApp()</code> to initialize the scene, and <code>simpleUpdate()</code> as event loop. <br/>
<br/>
The camera&#039;s default behaviour in SimpleApplication is to capture the mouse, which doesn&#039;t make sense in a Swing window. You have to deactivate and replace this behaviour by <code>flyCam.setDragToRotate(true);</code> when you initialize the application:
</p>
<pre>public void simpleInitApp&#40;&#41; &#123;
// activate windowed input behaviour
flyCam.setDragToRotate&#40;true&#41;;
// Set up inputs and load your scene as usual
...
&#125;</pre><p> In short: The first thing that is different is the <code>main()</code> method. We don&#039;t call start() on the SwingCanvasTest object as usual. Instead we create a Runnable() that creates and opens a standard Swing jFrame. In the runnable, we also create our SwingCanvasTest game with special settings, create a Canvas for it, and add that to the jFrame. Then we call startCanvas().</p></div><h2><a
name="main_and_runnable">Main() and Runnable()</a></h2><div
class="level2"><p> The Swing isn&#039;t thread-safe and doesn&#039;t allow us to keep the jME3 canvas up-to-date. This is why we create a runnable for the jME canvas and queue it in the AWT event thread, so it can be invoked &quot;later&quot; in the loop, when Swing is ready with updating its own stuff. <br/> <br/> In the SwingCanvasTest&#039;s main() method, create a queued runnable(). It will contain the jME canvas and the Swing frame.</p><pre> public static void main&#40;String&#91;&#93; args&#41; &#123;
&#125;</pre>
<p>
In short: The first thing that is different is the <code>main()</code> method. We don&#039;t call start() on the SwingCanvasTest object as usual. Instead we create a Runnable() that creates and opens a standard Swing jFrame. In the runnable, we also create our SwingCanvasTest game with special settings, create a Canvas for it, and add that to the jFrame. Then we call startCanvas().
</p>
</div>
<h2><a>Main() and Runnable()</a></h2>
<div>
<p>
The Swing isn&#039;t thread-safe and doesn&#039;t allow us to keep the jME3 canvas up-to-date. This is why we create a runnable for the jME canvas and queue it in the AWT event thread, so it can be invoked &quot;later&quot; in the loop, when Swing is ready with updating its own stuff. <br/>
<br/>
In the SwingCanvasTest&#039;s main() method, create a queued runnable(). It will contain the jME canvas and the Swing frame.
</p>
<pre> public static void main&#40;String&#91;&#93; args&#41; &#123;
java.awt.Runnable&#40;&#41; &#123;
public void run&#40;&#41; &#123;
// ... see below ...
&#125;
&#125;&#41;;
&#125;</pre></div><h3><a
name="creating_the_canvas">Creating the Canvas</a></h3><div
class="level3"><p> Here in the <code>run()</code> method, we start the jME application, create its canvas, create a Swing frame, and add everything together. <br/> <br/> Specify the com.jme3.system.AppSettings so jME knows the size of the Swing panel that we put it into. The application will not ask the user for display settings, you have to specify them in advance.</p><pre>AppSettings settings = new AppSettings&#40;true&#41;;
&#125;</pre>
</div>
<h3><a>Creating the Canvas</a></h3>
<div>
<p>
Here in the <code>run()</code> method, we start the jME application, create its canvas, create a Swing frame, and add everything together. <br/>
<br/>
Specify the com.jme3.system.AppSettings so jME knows the size of the Swing panel that we put it into. The application will not ask the user for display settings, you have to specify them in advance.
</p>
<pre>AppSettings settings = new AppSettings&#40;true&#41;;
settings.setWidth&#40;640&#41;;
settings.setHeight&#40;480&#41;;</pre><p> We create our canvas application SwingCanvasTest, and give it the settings. We manually create a canvas for this game and configure the com.jme3.system.JmeCanvasContext. The method setSystemListener() makes sure that the listener receives events relating to context creation, update, and destroy.</p><pre>SwingCanvasTest canvasApplication = new SwingCanvasTest&#40;&#41;;
settings.setHeight&#40;480&#41;;</pre>
<p>
We create our canvas application SwingCanvasTest, and give it the settings. We manually create a canvas for this game and configure the com.jme3.system.JmeCanvasContext. The method setSystemListener() makes sure that the listener receives events relating to context creation, update, and destroy.
</p>
<pre>SwingCanvasTest canvasApplication = new SwingCanvasTest&#40;&#41;;
canvasApplication.setSettings&#40;settings&#41;;
canvasApplication.createCanvas&#40;&#41;; // create canvas!
JmeCanvasContext ctx = &#40;JmeCanvasContext&#41; canvasApplication.getContext&#40;&#41;;
ctx.setSystemListener&#40;canvasApplication&#41;;
Dimension&#40;640, 480&#41;;
ctx.getCanvas&#40;&#41;.setPreferredSize&#40;dim&#41;;</pre><p> Note that we have not called start() on the application, as we would usually do in the main() method. We will call startCanvas() later instead.</p></div><h3><a
name="creating_the_swing_frame">Creating the Swing Frame</a></h3><div
class="level3"><p> Inside the run() method, you create the Swing window as you would usually do. Create an empty jFrame and add() components to it, or create a custom jFrame object in another class file (for example, by using the NetBeans <acronym
title="Graphical User Interface">GUI</acronym> builder) and create an instance of it here.
Which ever you do, let&#039;s call the jFrame <code>window</code>.</p><pre>JFrame&#40;&quot;Swing Application&quot;&#41;;
window.setDefaultCloseOperation&#40;FlowLayout&#40;&#41;&#41;; // a panel
ctx.getCanvas&#40;&#41;.setPreferredSize&#40;dim&#41;;</pre>
<p>
Note that we have not called start() on the application, as we would usually do in the main() method. We will call startCanvas() later instead.
</p>
</div>
<h3><a>Creating the Swing Frame</a></h3>
<div>
<p>
Inside the run() method, you create the Swing window as you would usually do. Create an empty jFrame and add() components to it, or create a custom jFrame object in another class file (for example, by using the NetBeans <acronym title="Graphical User Interface">GUI</acronym> builder) and create an instance of it here.
Which ever you do, let&#039;s call the jFrame <code>window</code>.
</p>
<pre>JFrame&#40;&quot;Swing Application&quot;&#41;;
window.setDefaultCloseOperation&#40;JFrame.EXIT_ON_CLOSE&#41;;</pre>
<p>
We create a standard JPanel inside the JFrame. Give it any Layout you wish – here we use a simple Flow Layout. Where the code sample says &quot;Some Swing Component&quot;, this is where you add your buttons and controls. <br/>
<br/>
The important step is to add() the canvas component into the panel, like all the other Swing components.
</p>
<pre>FlowLayout&#40;&#41;&#41;; // a panel
// add all your Swing components ...
panel.add&#40;new JButton&#40;&quot;Some Swing Component&quot;&#41;&#41;;
...
// add the JME canvas
panel.add&#40;ctx.getCanvas&#40;&#41;&#41;;</pre><p> OK, the jFrame and the panel are ready. We add the panel into the jFrame, and pack everything together. Set the window&#039;s visibility to true make it appear.</p><pre>window.add&#40;panel&#41;;
panel.add&#40;ctx.getCanvas&#40;&#41;&#41;;</pre>
<p>
OK, the jFrame and the panel are ready. We add the panel into the jFrame, and pack everything together. Set the window&#039;s visibility to true make it appear.
</p>
<pre>window.add&#40;panel&#41;;
window.pack&#40;&#41;;
window.setVisible&#40;true&#41;;</pre><p> Remember that we haven&#039;t called start() on the jME appliation yet? For the canvas, there is a special <code>startCanvas()</code> method that you must call now:</p><pre>canvasApplication.startCanvas&#40;&#41;;</pre><p> Clean, build, and run!</p></div><h2><a
name="navigation">Navigation</a></h2><div
class="level2"><p> Remember, to navigate in the scene, click and drag (!) the mouse, or press the WASD keys. Depending on your game you may even want to define custom inputs to handle navigation in this untypical environment.</p><div
class="tags"><span> <a
href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>, <a
href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:swing_canvas?do=export_xhtmlbody">view online version</a></em></p>
window.setVisible&#40;true&#41;;</pre>
<p>
Remember that we haven&#039;t called start() on the jME appliation yet? For the canvas, there is a special <code>startCanvas()</code> method that you must call now:
</p>
<pre>canvasApplication.startCanvas&#40;&#41;;</pre>
<p>
Clean, build, and run!
</p>
</div>
<h2><a>Navigation</a></h2>
<div>
<p>
Remember, to navigate in the scene, click and drag (!) the mouse, or press the WASD keys. Depending on your game you may even want to define custom inputs to handle navigation in this untypical environment.
</p>
<div><span>
<a href="/wiki/doku.php/tag:documentation?do=showtag&amp;tag=tag%3Adocumentation">documentation</a>,
<a href="/wiki/doku.php/tag:gui?do=showtag&amp;tag=tag%3Agui">gui</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:swing_canvas?do=export_xhtmlbody">view online version</a></em></p>

@ -1,95 +1,176 @@
<h1><a
name="terramonkey_-_jme3_s_terrain_system">TerraMonkey - jME3&#039;s Terrain System</a></h1><div
class="level1"><p> The goal of TerraMonkey is to provide a base implementation that will be usable for 80% of people&#039;s goals, while providing tools and a good foundation for the other 20% to build off of.</p></div><h2><a
name="overview">Overview</a></h2><div
class="level2"><p> TerraMonkey is a GeoMipMapping quad tree of terrain tiles that supports real time editing and texture splatting. That&#039;s a mouth full! Lets look at each part:</p><ul><li
class="level1"><div
class="li"> <strong>GeoMipMapping:</strong> a method of changing the level of detail (LOD) of geometry tiles based on how far away they are from the camera. Between the edges of two tiles, it will seam those edges together so you don&#039;t get gaps or holes. For an in-depth read on how it works, here is a pdf <a
href="http://www.flipcode.com/archives/article_geomipmaps.pdf">http://www.flipcode.com/archives/article_geomipmaps.pdf</a>.</div></li><li
class="level1"><div
class="li"> <strong>Quad Tree:</strong> The entire terrain structure is made up of TerrainPatches (these hold the actual meshes) as leaves in a quad tree (TerrainQuad). TerrainQuads are subdivided by 4 until they reach minimum size, then a TerrainPatch is created, and that is where the actual geometry mesh lives. This allows for fast culling of the terrain that you can&#039;t see.</div></li><li
class="level1"><div
class="li"> <strong>Splatting:</strong> The ability to paint multiple textures onto your terrain. What differs here from JME2 is that this is all done in a shader, no more render passes. So it performs much faster.</div></li><li
class="level1"><div
class="li"> <strong>Real-time editing:</strong> TerraMonkey will be editable in JMonkeyPlatform, and you will be able to do it in real time: raising and lowering terrain.</div></li></ul></div><h2><a
name="current_features">Current Features:</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> Support for up to 3 splat textures.</div></li><li
class="level1"><div
class="li"> GeoMipMapping</div></li><li
class="level1"><div
class="li"> can be supplied a heightmap</div></li></ul></div><h2><a
name="planned_features">Planned Features:</a></h2><div
class="level2"><ul><li
class="level1"><div
class="li"> jMonkeyPlatform terrain editor</div></li><li
class="level1"><div
class="li"> Support for up to 16 splat textures.</div></li><li
class="level1"><div
class="li"> Hydraulic erosion and procedural texture generation</div></li><li
class="level1"><div
class="li"> Streaming terrain (ie. &quot;infinite&quot; terrain)</div></li><li
class="level1"><div
class="li"> Holes: caves, cliffs</div></li></ul></div><h2><a
name="geo_mip_mapping">Geo Mip Mapping</a></h2><div
class="level2"><p> You have seen GeoMipMapping implemented in games before. This is where the farther away terrain has fewer polygons, and as you move closer, more polygons fill in. The whole terrain is divided into a grid of patches, and each one has its own LOD. The GeoMipMapping algorithm will look at each patch, and its neighbours, to determine how to render the geometry. It will seam the edges between two patches with different LOD.
<h1><a>TerraMonkey - jME3&#039;s Terrain System</a></h1>
<div>
<p>
The goal of TerraMonkey is to provide a base implementation that will be usable for 80% of people&#039;s goals, while providing tools and a good foundation for the other 20% to build off of. Check out the videos in the following announcements:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2011/06/17/infinite-terrains-with-terraingrid-new-features-in-terramonkey/"><param name="text" value="<html><u>New features</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/2011/07/03/terramonkey-more-textures-tools-and-undo/"><param name="text" value="<html><u>More textures and Tools</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Overview</a></h2>
<div>
<p>
TerraMonkey is a GeoMipMapping quad tree of terrain tiles that supports real time editing and texture splatting. That&#039;s a mouth full! Lets look at each part:
</p>
<ul>
<li><div> <strong>GeoMipMapping:</strong> a method of changing the level of detail (LOD) of geometry tiles based on how far away they are from the camera. Between the edges of two tiles, it will seam those edges together so you don&#039;t get gaps or holes. For an in-depth read on how it works, here is a pdf <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.flipcode.com/archives/article_geomipmaps.pdf"><param name="text" value="<html><u>http://www.flipcode.com/archives/article_geomipmaps.pdf</u></html>"><param name="textColor" value="blue"></object>.</div>
</li>
<li><div> <strong>Quad Tree:</strong> The entire terrain structure is made up of TerrainPatches (these hold the actual meshes) as leaves in a quad tree (TerrainQuad). TerrainQuads are subdivided by 4 until they reach minimum size, then a TerrainPatch is created, and that is where the actual geometry mesh lives. This allows for fast culling of the terrain that you can&#039;t see.</div>
</li>
<li><div> <strong>Splatting:</strong> The ability to paint multiple textures onto your terrain. What differs here from JME2 is that this is all done in a shader, no more render passes. So it performs much faster.</div>
</li>
<li><div> <strong>Real-time editing:</strong> TerraMonkey will be editable in JMonkeyPlatform, and you will be able to do it in real time: raising and lowering terrain.</div>
</li>
</ul>
</div>
<h2><a>Current Features:</a></h2>
<div>
<ul>
<li><div> Support for up to 3 splat textures.</div>
</li>
<li><div> GeoMipMapping</div>
</li>
<li><div> can be supplied a heightmap</div>
</li>
</ul>
</div>
<h2><a>Planned Features:</a></h2>
<div>
<ul>
<li><div> jMonkeyPlatform terrain editor</div>
</li>
<li><div> Support for up to 16 splat textures.</div>
</li>
<li><div> Hydraulic erosion and procedural texture generation</div>
</li>
<li><div> Streaming terrain (ie. &quot;infinite&quot; terrain)</div>
</li>
<li><div> Holes: caves, cliffs</div>
</li>
</ul>
</div>
<h2><a>Geo Mip Mapping</a></h2>
<div>
<p>
You have seen GeoMipMapping implemented in games before. This is where the farther away terrain has fewer polygons, and as you move closer, more polygons fill in. The whole terrain is divided into a grid of patches, and each one has its own LOD. The GeoMipMapping algorithm will look at each patch, and its neighbours, to determine how to render the geometry. It will seam the edges between two patches with different LOD.
This often leads to &quot;popping&quot; where you see the terrain switch from one LOD to another. TerraMonkey has been designed so you can swap out different LOD calculation algorithms based on what will look best for your game.
You can do this with the LodCalculator interface.
GeoMipMapping in TerraMonkey has been split into several parts: the terrain quad tree, and the LODGeomap. The geomap deals with the actual LOD and seaming algorithm. So if you want a different data structure for your terrain system, you can re-use this piece of code.
The quad tree (TerrainQuad and TerrainPatch) provide a means to organize the LODGeomaps, notify them of their neighbour&#039;s LOD change, and to update the geometry when the LOD does change.
To change the LOD it does this by changing the index buffer of the triangle strip, so the whole geometry doesn&#039;t have to be re-loaded onto the video card.</p><p> If you are eager, you can read up more detail how GeoMipMapping works here: <a
href="http://www.flipcode.com/archives/article_geomipmaps.pdf">www.flipcode.com/archives/article_geomipmaps.pdf</a></p></div><h2><a
name="terrain_quad_tree">Terrain Quad Tree</a></h2><div
class="level2"><p> TerraMonkey is a quad tree. Each node is a TerrainQuad, and each leaf is a TerrainPatch. A TerrainQuad has either 4 child TerrainQuads, or 4 child TerrainPatches. The TerrainPatch holds the actual mesh geometry. This structure is almost exactly the same as JME2&#039;s TerrainPage system. Except now each leaf has a reference to its neighbours, so it doesn&#039;t ever have to traverse the tree to get them.</p></div><h2><a
name="texture_splatting">Texture Splatting</a></h2><div
class="level2"><p> The default material for TerraMonkey is Terrain.j3md. This material combines an alphamap with several textures to produce the final texture.
To change the LOD it does this by changing the index buffer of the triangle strip, so the whole geometry doesn&#039;t have to be re-loaded onto the video card.
If you are eager, you can read up more detail how GeoMipMapping works here: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.flipcode.com/archives/article_geomipmaps.pdf"><param name="text" value="<html><u>www.flipcode.com/archives/article_geomipmaps.pdf</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<h2><a>Terrain Quad Tree</a></h2>
<div>
<p>
TerraMonkey is a quad tree. Each node is a TerrainQuad, and each leaf is a TerrainPatch. A TerrainQuad has either 4 child TerrainQuads, or 4 child TerrainPatches. The TerrainPatch holds the actual mesh geometry. This structure is almost exactly the same as JME2&#039;s TerrainPage system. Except now each leaf has a reference to its neighbours, so it doesn&#039;t ever have to traverse the tree to get them.
</p>
</div>
<h2><a>Texture Splatting</a></h2>
<div>
<p>
The default material for TerraMonkey is Terrain.j3md. This material combines an alphamap with several textures to produce the final texture.
Right now there is support for only 3 textures and an alpha map. This is in place until we finish the terrain editor in JMP, and then the texture support will be 16 textures.
It is only 3 right now so you can hand-paint them in a drawing program, like Photoshop, setting each splat texture in either Red, Green, or Blue. The test case has an example texture to show you how this works.</p><p> Along with getting more splat texture support, we will be adding in lighting and normal mapping support. The normal mapping isn&#039;t fully planned out yet. We need to decide how we are going to handle a normal map for each texture that is passed in. That could generate some very odd effects.
Thoughts, ideas, and recommendations are appreciated!</p></div><h2><a
name="code_sample">Code Sample</a></h2><div
class="level2"><p> First, we load our textures and the heightmap texture for the terrain</p><pre>// Create material from Terrain Material Definition
It is only 3 right now so you can hand-paint them in a drawing program, like Photoshop, setting each splat texture in either Red, Green, or Blue. The test case has an example texture to show you how this works.
Along with getting more splat texture support, we will be adding in lighting and normal mapping support. The normal mapping isn&#039;t fully planned out yet. We need to decide how we are going to handle a normal map for each texture that is passed in. That could generate some very odd effects.
Thoughts, ideas, and recommendations are appreciated!
</p>
</div>
<h2><a>Code Sample</a></h2>
<div>
<p>
First, we load our textures and the heightmap texture for the terrain
</p>
<pre>// Create material from Terrain Material Definition
matRock = new Material&#40;assetManager, &quot;Common/MatDefs/Terrain/Terrain.j3md&quot;&#41;;
// Load alpha map (for splat textures)
matRock.setTexture&#40;&quot;m_Alpha&quot;, assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/alphamap.png&quot;&#41;&#41;;
// load heightmap image (for the terrain heightmap)
Texture heightMapImage = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/mountains512.png&quot;&#41;;
&nbsp;
// load grass texture
Texture grass = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/grass.jpg&quot;&#41;;
grass.setWrap&#40;WrapMode.Repeat&#41;;
matRock.setTexture&#40;&quot;m_Tex1&quot;, grass&#41;;
matRock.setFloat&#40;&quot;m_Tex1Scale&quot;, 64f&#41;;
&nbsp;
// load dirt texture
Texture dirt = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/dirt.jpg&quot;&#41;;
dirt.setWrap&#40;WrapMode.Repeat&#41;;
matRock.setTexture&#40;&quot;m_Tex2&quot;, dirt&#41;;
matRock.setFloat&#40;&quot;m_Tex2Scale&quot;, 32f&#41;;
&nbsp;
// load rock texture
Texture rock = assetManager.loadTexture&#40;&quot;Textures/Terrain/splat/road.jpg&quot;&#41;;
rock.setWrap&#40;WrapMode.Repeat&#41;;
matRock.setTexture&#40;&quot;m_Tex3&quot;, rock&#41;;
matRock.setFloat&#40;&quot;m_Tex3Scale&quot;, 128f&#41;;</pre><p> We create the heightmap from the <code>heightMapImage</code>.</p><pre>AbstractHeightMap heightmap = null;
matRock.setFloat&#40;&quot;m_Tex3Scale&quot;, 128f&#41;;</pre>
<p>
We create the heightmap from the <code>heightMapImage</code>.
</p>
<pre>AbstractHeightMap heightmap = null;
heightmap = new ImageBasedHeightMap&#40;
ImageToAwt.convert&#40;heightMapImage.getImage&#40;&#41;, false, true, 0&#41;, 1f&#41;;
heightmap.load&#40;&#41;;</pre><p> Next we create the actual terrain.</p><ul><li
class="level1"><div
class="li"> The terrain tiles are 65x65.</div></li><li
class="level1"><div
class="li"> The total size of the terrain is 513x513, but it can easily be up to 1025x1025.</div></li><li
class="level1"><div
class="li"> It uses the heightmap to generate the height values.</div></li></ul><pre>terrain = new TerrainQuad&#40;&quot;terrain&quot;, 65, 513, heightmap.getHeightMap&#40;&#41;&#41;;
heightmap.load&#40;&#41;;</pre>
<p>
Next we create the actual terrain.
</p>
<ul>
<li><div> The terrain tiles are 65x65.</div>
</li>
<li><div> The total size of the terrain is 513x513, but it can easily be up to 1025x1025.</div>
</li>
<li><div> It uses the heightmap to generate the height values.</div>
</li>
</ul>
<pre>terrain = new TerrainQuad&#40;&quot;terrain&quot;, 65, 513, heightmap.getHeightMap&#40;&#41;&#41;;
terrain.setMaterial&#40;matRock&#41;;
terrain.setModelBound&#40;new BoundingBox&#40;&#41;&#41;;
terrain.updateModelBound&#40;&#41;;
terrain.setLocalScale&#40;2f, 1f, 2f&#41;; // scale to make it less steep
&nbsp;
List&lt;Camera&gt; cameras = new ArrayList&lt;Camera&gt;&#40;&#41;;
cameras.add&#40;getCamera&#40;&#41;&#41;;
TerrainLodControl control = new TerrainLodControl&#40;terrain, cameras&#41;;
terrain.addControl&#40;control&#41;;
&nbsp;
rootNode.attachChild&#40;terrain&#41;;</pre><p> PS: As an alternative to an image-based height map, you can also generate a Hill hightmap:</p><pre>heightmap = new HillHeightMap&#40;1025, 1000, 50, 100, &#40;byte&#41; 3&#41;;</pre></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:terrain?do=export_xhtmlbody">view online version</a></em></p>
rootNode.attachChild&#40;terrain&#41;;</pre>
<p>
PS: As an alternative to an image-based height map, you can also generate a Hill hightmap:
</p>
<pre>heightmap = new HillHeightMap&#40;1025, 1000, 50, 100, &#40;byte&#41; 3&#41;;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:terrain?do=export_xhtmlbody">view online version</a></em></p>

@ -0,0 +1,324 @@
<h2><a>Terrain Collision</a></h2>
<div>
<p>
This tutorial expands the HelloTerrain tutorial and makes the terrain solid. You combine what you learned in <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html">Hello Terrain</a> and <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_collision.html">Hello Collision</a> and add a CollisionShape to the terrain. The terrain&#039;s CollisionShape lets the first-person player (who is also a CollisionShape) collide with the terrain, i.e. walk on it and stand on it.
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<pre>package jme3test.helloworld;
&nbsp;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Node;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import java.util.ArrayList;
import java.util.List;
import jme3tools.converters.ImageToAwt;
&nbsp;
<span>/**
* This demo shows a terrain with collision detection,
* that you can walk around in with a first-person perspective.
* This code combines HelloCollision and HelloTerrain.
*/</span>
public class HelloTerrainCollision extends SimpleApplication
implements ActionListener &#123;
&nbsp;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f&#40;&#41;;
private boolean left = false, right = false, up = false, down = false;
private TerrainQuad terrain;
private Material mat_terrain;
&nbsp;
public static void main&#40;String&#91;&#93; args&#41; &#123;
HelloTerrainCollision app = new HelloTerrainCollision&#40;&#41;;
app.start&#40;&#41;;
&#125;
&nbsp;
@Override
public void simpleInitApp&#40;&#41; &#123;
/** Set up Physics */
bulletAppState = new BulletAppState&#40;&#41;;
stateManager.attach&#40;bulletAppState&#41;;
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);
&nbsp;
flyCam.setMoveSpeed&#40;100&#41;;
setUpKeys&#40;&#41;;
&nbsp;
/** 1. Create terrain material and load four textures into it. */
mat_terrain = new Material&#40;assetManager,
&quot;Common/MatDefs/Terrain/Terrain.j3md&quot;&#41;;
&nbsp;
/** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
mat_terrain.setTexture&#40;&quot;Alpha&quot;, assetManager.loadTexture&#40;
&quot;Textures/Terrain/splat/alphamap.png&quot;&#41;&#41;;
&nbsp;
/** 1.2) Add GRASS texture into the red layer (Tex1). */
Texture grass = assetManager.loadTexture&#40;
&quot;Textures/Terrain/splat/grass.jpg&quot;&#41;;
grass.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex1&quot;, grass&#41;;
mat_terrain.setFloat&#40;&quot;Tex1Scale&quot;, 64f&#41;;
&nbsp;
/** 1.3) Add DIRT texture into the green layer (Tex2) */
Texture dirt = assetManager.loadTexture&#40;
&quot;Textures/Terrain/splat/dirt.jpg&quot;&#41;;
dirt.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex2&quot;, dirt&#41;;
mat_terrain.setFloat&#40;&quot;Tex2Scale&quot;, 32f&#41;;
&nbsp;
/** 1.4) Add ROAD texture into the blue layer (Tex3) */
Texture rock = assetManager.loadTexture&#40;
&quot;Textures/Terrain/splat/road.jpg&quot;&#41;;
rock.setWrap&#40;WrapMode.Repeat&#41;;
mat_terrain.setTexture&#40;&quot;Tex3&quot;, rock&#41;;
mat_terrain.setFloat&#40;&quot;Tex3Scale&quot;, 128f&#41;;
&nbsp;
/** 2. Create the height map */
AbstractHeightMap heightmap = null;
Texture heightMapImage = assetManager.loadTexture&#40;
&quot;Textures/Terrain/splat/mountains512.png&quot;&#41;;
heightmap = new ImageBasedHeightMap&#40;
ImageToAwt.convert&#40;heightMapImage.getImage&#40;&#41;, false, true, 0&#41;&#41;;
heightmap.load&#40;&#41;;
&nbsp;
<span>/** 3. We have prepared material and heightmap.
* Now we create the actual terrain:
* 3.1) Create a TerrainQuad and name it &quot;my terrain&quot;.
* 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
* 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
* 3.4) As LOD step scale we supply Vector3f(1,1,1).
* 3.5) We supply the prepared heightmap itself.
*/</span>
terrain = new TerrainQuad&#40;&quot;my terrain&quot;, 65, 513, heightmap.getHeightMap&#40;&#41;&#41;;
&nbsp;
/** 4. We give the terrain its material, position &amp; scale it, and attach it. */
terrain.setMaterial&#40;mat_terrain&#41;;
terrain.setLocalTranslation&#40;0, -100, 0&#41;;
terrain.setLocalScale&#40;2f, 1f, 2f&#41;;
rootNode.attachChild&#40;terrain&#41;;
&nbsp;
/** 5. The LOD (level of detail) depends on were the camera is: */
List&lt;Camera&gt; cameras = new ArrayList&lt;Camera&gt;&#40;&#41;;
cameras.add&#40;getCamera&#40;&#41;&#41;;
TerrainLodControl control = new TerrainLodControl&#40;terrain, cameras&#41;;
terrain.addControl&#40;control&#41;;
&nbsp;
/** 6. Add physics: */
// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.*/
CollisionShape terrainShape =
CollisionShapeFactory.createMeshShape&#40;&#40;Node&#41; terrain&#41;;
landscape = new RigidBodyControl&#40;terrainShape, 0&#41;;
terrain.addControl&#40;landscape&#41;;
&nbsp;
// We set up collision detection for the player by creating
// a capsule collision shape and a CharacterControl.
// The CharacterControl offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape&#40;1.5f, 6f, 1&#41;;
player = new CharacterControl&#40;capsuleShape, 0.05f&#41;;
player.setJumpSpeed&#40;20&#41;;
player.setFallSpeed&#40;30&#41;;
player.setGravity&#40;30&#41;;
player.setPhysicsLocation&#40;new Vector3f&#40;0, 10, 0&#41;&#41;;
&nbsp;
// We attach the scene and the player to the rootnode and the physics space,
// to make them appear in the game world.
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;terrain&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;player&#41;;
&nbsp;
&#125;
<span>/** We over-write some navigational key mappings here, so we can
* add physics-controlled walking and jumping: */</span>
private void setUpKeys&#40;&#41; &#123;
inputManager.addMapping&#40;&quot;Left&quot;, new KeyTrigger&#40;KeyInput.KEY_A&#41;&#41;;
inputManager.addMapping&#40;&quot;Right&quot;, new KeyTrigger&#40;KeyInput.KEY_D&#41;&#41;;
inputManager.addMapping&#40;&quot;Up&quot;, new KeyTrigger&#40;KeyInput.KEY_W&#41;&#41;;
inputManager.addMapping&#40;&quot;Down&quot;, new KeyTrigger&#40;KeyInput.KEY_S&#41;&#41;;
inputManager.addMapping&#40;&quot;Jump&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;
inputManager.addListener&#40;this, &quot;Left&quot;&#41;;
inputManager.addListener&#40;this, &quot;Right&quot;&#41;;
inputManager.addListener&#40;this, &quot;Up&quot;&#41;;
inputManager.addListener&#40;this, &quot;Down&quot;&#41;;
inputManager.addListener&#40;this, &quot;Jump&quot;&#41;;
&#125;
&nbsp;
<span>/** These are our custom actions triggered by key presses.
* We do not walk yet, we just keep track of the direction the user pressed. */</span>
public void onAction&#40;String binding, boolean value, float tpf&#41; &#123;
if &#40;binding.equals&#40;&quot;Left&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123; left = true; &#125; else &#123; left = false; &#125;
&#125; else if &#40;binding.equals&#40;&quot;Right&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123; right = true; &#125; else &#123; right = false; &#125;
&#125; else if &#40;binding.equals&#40;&quot;Up&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123; up = true; &#125; else &#123; up = false; &#125;
&#125; else if &#40;binding.equals&#40;&quot;Down&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123; down = true; &#125; else &#123; down = false; &#125;
&#125; else if &#40;binding.equals&#40;&quot;Jump&quot;&#41;&#41; &#123;
player.jump&#40;&#41;;
&#125;
&#125;
&nbsp;
<span>/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/</span>
@Override
public void simpleUpdate&#40;float tpf&#41; &#123;
Vector3f camDir = cam.getDirection&#40;&#41;.clone&#40;&#41;.multLocal&#40;0.6f&#41;;
Vector3f camLeft = cam.getLeft&#40;&#41;.clone&#40;&#41;.multLocal&#40;0.4f&#41;;
walkDirection.set&#40;0, 0, 0&#41;;
if &#40;left&#41; &#123; walkDirection.addLocal&#40;camLeft&#41;; &#125;
if &#40;right&#41; &#123; walkDirection.addLocal&#40;camLeft.negate&#40;&#41;&#41;; &#125;
if &#40;up&#41; &#123; walkDirection.addLocal&#40;camDir&#41;; &#125;
if &#40;down&#41; &#123; walkDirection.addLocal&#40;camDir.negate&#40;&#41;&#41;; &#125;
player.setWalkDirection&#40;walkDirection&#41;;
cam.setLocation&#40;player.getPhysicsLocation&#40;&#41;&#41;;
&#125;
&#125;</pre>
<p>
To try this code, create a New Project → JME3 → BasicGame using the default settings. Paste the sample code over the pregenerated Main.java class. Chnage the package to &quot;mygame&quot; if necessary. Open the Project Properties, Libraries, and add the <code>jme3-test-data</code> library to make certain you have all the files.
</p>
<p>
Compile and run the code. You should see a terrain. You can use the WASD keys and the mouse to run up and down the hills.
</p>
</div>
<h2><a>Understanding the Code</a></h2>
<div>
</div>
<h3><a>The Terrain Code</a></h3>
<div>
<p>
Read <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html">Hello Terrain</a> for details of the following parts that we reuse:
</p>
<ol>
<li><div> The <code>AbstractHeightMap</code> is an efficient way to describe the shape of the terrain.</div>
</li>
<li><div> The <code>Terrain.j3md</code>-based Material and its texture layers let you colorize rocky mountain, grassy valleys, and a paved path criss-crossing over the landscape. </div>
</li>
<li><div> The TerrainQuad is the finished <code>terrain</code> Spatial that you attach to the rootNode.</div>
</li>
</ol>
</div>
<h3><a>The Collision Detection Code</a></h3>
<div>
<p>
Read <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_collision.html">Hello Collision</a> for details of the following parts that we reuse:
</p>
<ol>
<li><div> The <code>BulletAppState</code> lines activate physics.</div>
</li>
<li><div> The <code>ActionListener</code> (<code>onAction()</code>) lets you reconfigure the input handling for the first-person player, so it takes collision detection into account.</div>
</li>
<li><div> The custom <code>setUpKeys()</code> method loads your reconfigured input handlers. They now don&#039;t just walk blindly, but calculate the <code>walkDirection</code> vector that we need for collision detection.</div>
</li>
<li><div> <code>simpleUpdate()</code> uses the <code>walkDirection</code> vector and makes the character walk, while taking obstacles and solid walls/floor into account. <pre>player.setWalkDirection&#40;walkDirection&#41;;</pre>
</div>
</li>
<li><div> The RigidBodyControl <code>landscape</code> is the CollisionShape of the terrain.</div>
</li>
<li><div> The physical first-person player is a CapsuleCollisionShape with a CharacterControl.</div>
</li>
</ol>
</div>
<h3><a>Combining the Two</a></h3>
<div>
<p>
Here are the changed parts to combine the two:
</p>
<ol>
<li><div> The CollisionShapeFactory creates the CollisionShape <code>terrainShape</code> for the <code>terrain</code> node.</div>
</li>
<li><div> Out of the <code>terrainShape</code>, you create a static (zero-mass) RigidBodyControl <code>landscape</code>. </div>
</li>
<li><div> Add the <code>landscape</code> control to the <code>terrain</code> to make it physical.</div>
</li>
</ol>
<pre>/** 6. Add physics: */
CollisionShape terrainShape =
CollisionShapeFactory.createMeshShape&#40;&#40;Node&#41; terrain&#41;;
landscape = new RigidBodyControl&#40;terrainShape, 0&#41;;
terrain.addControl&#40;landscape&#41;; </pre>
<p>
You attach the <code>terrain</code> and the first-person <code>player</code> to the rootNode, and to the physics space, to make them appear in the game world.
</p>
<pre> bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;terrain&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;player&#41;;</pre>
</div>
<h2><a>Conclusion</a></h2>
<div>
<p>
You see that you can combine snippets of sample code (such as HelloTerrain and HelloCollision), and create a new application from it that combines two features into soemthing new.
</p>
<p>
You should spawn high up in the area and fall down to the map, giving you a few seconds to survey the area. Then walk around and see how you like the lay of the land.
</p>
<hr />
<p>
See also:
</p>
<ul>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/beginner/hello_terrain.html">Hello Terrain</a>,</div>
</li>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/terrain.html">Terrain</a></div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:terrain?do=showtag&amp;tag=tag%3Aterrain">terrain</a>,
<a href="/wiki/doku.php/tag:collision?do=showtag&amp;tag=tag%3Acollision">collision</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:terrain_collision?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 22 KiB

@ -1,52 +1,74 @@
<h1><a
name="update_loop">Update Loop</a></h1><div
class="level1"><p> Extending your application from com.jme3.app.<a
href="/com/jme3/gde/core/docs/jme3/intermediate/simpleapplication.html">SimpleApplication</a> provides you with an update loop. This is where you implement your game logic (game mechanics).</p><p> Examples: Here you remote-control NPCs (computer controlled characters), generate game events, and respond to user input.</p><ol><li
class="level1"><div
class="li"> Initialization (<code>simpleInit()</code>)</div></li><li
class="level1"><div
class="li"> If exit is requested, then cleanup and destroy</div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">Input handling</a> (listeners)</div></li><li
class="level1"><div
class="li"> Update game state</div><ol><li
class="level2"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> update</div></li><li
class="level2"><div
class="li"> User update (<code>simpleUpdate()</code> method)</div></li><li
class="level2"><div
class="li"> Entity logical update (<a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a>)</div></li></ol></li><li
class="level1"><div
class="li"> render</div><ol><li
class="level2"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> rendering</div></li><li
class="level2"><div
class="li"> Scene rendering</div></li><li
class="level2"><div
class="li"> User rendering (<code>simpleRender()</code> method)</div></li></ol></li><li
class="level1"><div
class="li"> Repeat (goto 2)</div></li></ol></div><h2><a
name="usage">Usage</a></h2><div
class="level2"><p> Use…</p><ul><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> to implement global game mechanics <br/> Example: Physics, Global gameplay control</div></li><li
class="level1"><div
class="li"> <a
href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> to implement entity behavior <br/> Example: Enemy AI</div></li><li
class="level1"><div
class="li"> <code>simpleUpdate()</code> to implement the rest, or for testing during development.</div></li></ul><div
class="tags"><span> <a
href="/wiki/doku.php/tag:basegame?do=showtag&amp;tag=tag%3Abasegame">basegame</a>, <a
href="/wiki/doku.php/tag:controller?do=showtag&amp;tag=tag%3Acontroller">controller</a>, <a
href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>, <a
href="/wiki/doku.php/tag:init?do=showtag&amp;tag=tag%3Ainit">init</a>, <a
href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>, <a
href="/wiki/doku.php/tag:loop?do=showtag&amp;tag=tag%3Aloop">loop</a>, <a
href="/wiki/doku.php/tag:states?do=showtag&amp;tag=tag%3Astates">states</a>, <a
href="/wiki/doku.php/tag:state?do=showtag&amp;tag=tag%3Astate">state</a> </span></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:update_loop?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Update Loop</a></h1>
<div>
<p>
Extending your application from com.jme3.app.<a href="/com/jme3/gde/core/docs/jme3/intermediate/simpleapplication.html">SimpleApplication</a> provides you with an update loop. This is where you implement your game logic (game mechanics).
</p>
<p>
Examples: Here you remote-control NPCs (computer controlled characters), generate game events, and respond to user input.
</p>
<ul>
<li><div> Initialization – <code>simpleInitApp()</code> method</div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">Input handling</a> – input listeners</div>
</li>
<li><div> Update game state</div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> update</div>
</li>
<li><div> User update – <code>simpleUpdate()</code> method</div>
</li>
<li><div> Entity logical update – <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a></div>
</li>
</ol>
</li>
<li><div> render</div>
<ol>
<li><div> <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">Application States</a> rendering</div>
</li>
<li><div> Scene rendering</div>
</li>
<li><div> User rendering – <code>simpleRender()</code> method</div>
</li>
</ol>
</li>
</ol>
</li>
<li><div> If exit is requested, then cleanup and destroy</div>
</li>
<li><div> Repeat</div>
</li>
</ul>
</div>
<h2><a>Usage</a></h2>
<div>
<p>
There are two strategies how advanced developers can spread out their init and update code over several Java objects:
</p>
<ul>
<li><div> Move code blocks from the simpleInitApp() method to <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">AppStates</a>.</div>
</li>
<li><div> Move code blocks from the simpleUpdate() method to <a href="/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html">Custom Controls</a> to control entity behavior.</div>
</li>
</ul>
<div><span>
<a href="/wiki/doku.php/tag:basegame?do=showtag&amp;tag=tag%3Abasegame">basegame</a>,
<a href="/wiki/doku.php/tag:controller?do=showtag&amp;tag=tag%3Acontroller">controller</a>,
<a href="/wiki/doku.php/tag:input?do=showtag&amp;tag=tag%3Ainput">input</a>,
<a href="/wiki/doku.php/tag:init?do=showtag&amp;tag=tag%3Ainit">init</a>,
<a href="/wiki/doku.php/tag:keyinput?do=showtag&amp;tag=tag%3Akeyinput">keyinput</a>,
<a href="/wiki/doku.php/tag:loop?do=showtag&amp;tag=tag%3Aloop">loop</a>,
<a href="/wiki/doku.php/tag:states?do=showtag&amp;tag=tag%3Astates">states</a>,
<a href="/wiki/doku.php/tag:state?do=showtag&amp;tag=tag%3Astate">state</a>
</span></div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:update_loop?do=export_xhtmlbody">view online version</a></em></p>

@ -1,89 +1,207 @@
<h1><a
name="controlling_a_physical_vehicle">Controlling a Physical Vehicle</a></h1><div
class="level1"><p> For physical vehicles, jME&#039;s uses the jBullet ray-cast vehicle. In this vehicle implementation, the physical chassis &#039;floats&#039; along on four non-physical vertical rays.</p><p> Internally, each wheel casts a ray down, and using the ray&#039;s intersection point, jBullet calculates the suspension length, and the suspension force. The suspension force is applied to the chassis, keeping it from hitting the ground. The friction force is calculated for each wheel where the ray intersects with the ground. Friction is applied as a sideways and forwards force. <sup><a
href="#fn__1">1)</a></sup></p><p> This article shows how you use this vehicle implementation in a jME3 application.</p><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:physics-vehicle.png?id=jme3%3Aadvanced%3Avehicles"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/physics-vehicle.png" class="mediacenter" alt="" /></a></p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><p> Full code samples are here:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsCar.java">TestPhysicsCar.java</a></div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java">TestFancyCar.java</a></div></li></ul></div><h2><a
name="overview_of_this_physics_application">Overview of this Physics Application</a></h2><div
class="level2"><p> The goal is to create a physical vehicle with wheels that can be steered and that interacts (collides with) with the floor and obstacles.</p><ol><li
class="level1"><div
class="li"> Create a SimpleApplication with a <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a></div><ul><li
class="level2"><div
class="li"> This gives us a PhysicsSpace for PhysicsNodes</div></li></ul></li><li
class="level1"><div
class="li"> Create a VehicleControl + CompoundCollisionShape for the physical vehicle behaviour</div><ol><li
class="level2"><div
class="li"> Set physical properties of the vehicle, such as suspension.</div></li></ol></li><li
class="level1"><div
class="li"> Create a VehicleNode for the car model</div><ol><li
class="level2"><div
class="li"> Create a box plus 4 cylinders as wheels (using <code>vehicle.addWheel()</code>).</div></li><li
class="level2"><div
class="li"> Add the VehicleControl behaviour to the VehicleNode geometry.</div></li></ol></li><li
class="level1"><div
class="li"> Create a RigidBodyControl and CollisionShape for the floor</div></li><li
class="level1"><div
class="li"> Map key triggers and add input listeners</div><ul><li
class="level2"><div
class="li"> Navigational commands Left, Right, Foward, Brake.</div></li></ul></li><li
class="level1"><div
class="li"> Define the steering actions to be triggered by the key events.</div><ul><li
class="level2"><div
class="li"> <code>vehicle.steer()</code></div></li><li
class="level2"><div
class="li"> <code>vehicle.accelerate()</code></div></li><li
class="level2"><div
class="li"> <code>vehicle.brake()</code></div></li></ul></li></ol></div><h2><a
name="creating_the_vehicle_chassis">Creating the Vehicle Chassis</a></h2><div
class="level2"><p> The vehicle that we create here in the <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsCar.java">TestPhysicsCar.java</a> example is just a &quot;box on wheels&quot;, a basic vehicle shape that you can replace with a fancy car model, as demonstrated in <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java">TestFancyCar.java</a>.</p><p> Every physical object must have a collision shape, that we prepare first. For the vehicle, we choose a compound collision shape that is made up of a box-shaped body of the right size for the vehicle. We will add the wheels later.</p><pre>CompoundCollisionShape compoundShape = new CompoundCollisionShape&#40;&#41;;
BoxCollisionShape box = new BoxCollisionShape&#40;new Vector3f&#40;1.2f, 0.5f, 2.4f&#41;&#41;;</pre><p> <strong>Best Practice:</strong> We attach the BoxCollisionShape (the vehicle body) to the CompoundCollisionShape at a Vector of (0,1,0): This shifts the effective center of mass of the BoxCollisionShape downwards to 0,-1,0 and makes a moving vehicle more stable!</p><pre>compoundShape.addChildShape&#40;box, new Vector3f&#40;0, 1, 0&#41;&#41;;</pre><p> Any kind of geometry can make up the visible part of the vehicle, here we use a wireframe box. We create a node that we use to group the geometry.</p><pre> Node vehicleNode=new Node&#40;&quot;vehicleNode&quot;&#41;;
vehicle = new VehicleControl&#40;compoundShape, 400&#41;;
vehicleNode.addControl&#40;vehicle&#41;;</pre><p> We initialize the Vehicle Control with the compound shape, and set its mass to a heavy value, 400f. The Vehicle Control represents the car&#039;s physical behaviour.</p><pre>vehicle = new VehicleControl&#40;compoundShape, 400&#41;;</pre><p> Finally we add the behaviour (VehicleControl) to the visible Geometry (node).</p><pre>vehicleNode.addControl&#40;vehicle&#41;;</pre><p> We configure the physical properties of the vehicle&#039;s suspension: Compresion, Damping, Stiffness, and MaxSuspenionForce. Picking workable values for the wheel suspension can be tricky – for background info have a look at these <a
href="https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en">Suspension Settings Tips</a>. For now, let&#039;s work with the following values:</p><pre> float stiffness = 60.0f;//200=f1 car
float compValue = .3f; //(should be lower than damp)
float dampValue = .4f;
vehicle.setSuspensionCompression&#40;compValue * 2.0f * FastMath.sqrt&#40;stiffness&#41;&#41;;
vehicle.setSuspensionDamping&#40;dampValue * 2.0f * FastMath.sqrt&#40;stiffness&#41;&#41;;
vehicle.setSuspensionStiffness&#40;stiffness&#41;;
vehicle.setMaxSuspensionForce&#40;10000.0f&#41;;</pre><p> We now have a node <code>vehicleNode</code> with a visible &quot;car&quot; geometry, which acts like a vehicle. One thing that&#039;s missing are wheels.</p></div><h2><a
name="adding_the_wheels">Adding the Wheels</a></h2><div
class="level2"><p> We create four wheel Geometries and add them to the vehicle. Our wheel geometries are simple, non-physical discs (flat Cylinders), they are just visual decorations. Note that the physical wheel behaviour (the com.jme3.bullet.objects.VehicleWheel objects) is created internally by the <code>vehicle.addWheel()</code> method.</p><p> The <code>addWheel()</code> method sets following properties:</p><ul><li
class="level1"><div
class="li"> Vector3f connectionPoint – Coordinate where the suspension connects to the chassis (internally, this is where the Ray is casted downwards).</div></li><li
class="level1"><div
class="li"> Vector3f direction – Wheel direction is typically a (0,-1,0) vector.</div></li><li
class="level1"><div
class="li"> Vector3f axle – Axle direction is typically a (-1,0,0) vector.</div></li><li
class="level1"><div
class="li"> float suspensionRestLength – Suspension rest length in world units</div></li><li
class="level1"><div
class="li"> float wheelRadius – Wheel radius in world units</div></li><li
class="level1"><div
class="li"> boolean isFrontWheel – Whether this wheel is one of the steering wheels. <br/> Front wheels are the ones that rotate visibly when the vehicle turns.</div></li></ul><p> We initialize a few variables that we will reuse when we add the four wheels. yOff, etc, are the particular wheel offsets for our small vehicle model.</p><pre>Vector3f wheelDirection = new Vector3f&#40;0, -1, 0&#41;;
<h1><a>Controlling a Physical Vehicle</a></h1>
<div>
<p>
For physical vehicles, jME&#039;s uses the jBullet ray-cast vehicle. In this vehicle implementation, the physical chassis &#039;floats&#039; along on four non-physical vertical rays.
</p>
<p>
Internally, each wheel casts a ray down, and using the ray&#039;s intersection point, jBullet calculates the suspension length, and the suspension force. The suspension force is applied to the chassis, keeping it from hitting the ground. The friction force is calculated for each wheel where the ray intersects with the ground. Friction is applied as a sideways and forwards force. <sup><a href="#fn__1">1)</a></sup>
</p>
<p>
This article shows how you use this vehicle implementation in a jME3 application.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/physics-vehicle.png">
</p>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
Full code samples are here:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsCar.java"><param name="text" value="<html><u>TestPhysicsCar.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java"><param name="text" value="<html><u>TestFancyCar.java</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<h2><a>Overview of this Physics Application</a></h2>
<div>
<p>
The goal is to create a physical vehicle with wheels that can be steered and that interacts (collides with) with the floor and obstacles.
</p>
<ol>
<li><div> Create a SimpleApplication with a <a href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a> </div>
<ul>
<li><div> This gives us a PhysicsSpace for PhysicsNodes</div>
</li>
</ul>
</li>
<li><div> Create a VehicleControl + CompoundCollisionShape for the physical vehicle behaviour</div>
<ol>
<li><div> Set physical properties of the vehicle, such as suspension.</div>
</li>
</ol>
</li>
<li><div> Create a VehicleNode for the car model</div>
<ol>
<li><div> Create a box plus 4 cylinders as wheels (using <code>vehicle.addWheel()</code>).</div>
</li>
<li><div> Add the VehicleControl behaviour to the VehicleNode geometry.</div>
</li>
</ol>
</li>
<li><div> Create a RigidBodyControl and CollisionShape for the floor</div>
</li>
<li><div> Map key triggers and add input listeners</div>
<ul>
<li><div> Navigational commands Left, Right, Foward, Brake.</div>
</li>
</ul>
</li>
<li><div> Define the steering actions to be triggered by the key events.</div>
<ul>
<li><div> <code>vehicle.steer()</code></div>
</li>
<li><div> <code>vehicle.accelerate()</code></div>
</li>
<li><div> <code>vehicle.brake()</code></div>
</li>
</ul>
</li>
</ol>
</div>
<h2><a>Creating the Vehicle Chassis</a></h2>
<div>
<p>
The vehicle that we create here in the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestPhysicsCar.java"><param name="text" value="<html><u>TestPhysicsCar.java</u></html>"><param name="textColor" value="blue"></object> example is just a &quot;box on wheels&quot;, a basic vehicle shape that you can replace with a fancy car model, as demonstrated in <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java"><param name="text" value="<html><u>TestFancyCar.java</u></html>"><param name="textColor" value="blue"></object>.
</p>
<p>
Every physical object must have a collision shape, that we prepare first. For the vehicle, we choose a compound collision shape that is made up of a box-shaped body of the right size for the vehicle. We will add the wheels later.
</p>
<pre>CompoundCollisionShape compoundShape = new CompoundCollisionShape&#40;&#41;;
BoxCollisionShape box = new BoxCollisionShape&#40;new Vector3f&#40;1.2f, 0.5f, 2.4f&#41;&#41;;</pre>
<p>
<strong>Best Practice:</strong> We attach the BoxCollisionShape (the vehicle body) to the CompoundCollisionShape at a Vector of (0,1,0): This shifts the effective center of mass of the BoxCollisionShape downwards to 0,-1,0 and makes a moving vehicle more stable!
</p>
<pre>compoundShape.addChildShape&#40;box, new Vector3f&#40;0, 1, 0&#41;&#41;;</pre>
<p>
Any kind of geometry can make up the visible part of the vehicle, here we use a wireframe box. We create a node that we use to group the geometry.
</p>
<pre>Node vehicleNode=new Node&#40;&quot;vehicleNode&quot;&#41;;
vehicle = new VehicleControl&#40;compoundShape, 400&#41;;
vehicleNode.addControl&#40;vehicle&#41;;</pre>
<p>
We initialize the Vehicle Control with the compound shape, and set its mass to a heavy value, 400f. The Vehicle Control represents the car&#039;s physical behaviour.
</p>
<pre>vehicle = new VehicleControl&#40;compoundShape, 400&#41;;</pre>
<p>
Finally we add the behaviour (VehicleControl) to the visible Geometry (node).
</p>
<pre>vehicleNode.addControl&#40;vehicle&#41;;</pre>
<p>
We configure the physical properties of the vehicle&#039;s suspension: Compresion, Damping, Stiffness, and MaxSuspenionForce. Picking workable values for the wheel suspension can be tricky – for background info have a look at these <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en"><param name="text" value="<html><u>Suspension Settings Tips</u></html>"><param name="textColor" value="blue"></object>. For now, let&#039;s work with the following values:
</p>
<pre>float stiffness = 60.0f;//200=f1 car
float compValue = .3f; //(should be lower than damp)
float dampValue = .4f;
vehicle.setSuspensionCompression&#40;compValue * 2.0f * FastMath.sqrt&#40;stiffness&#41;&#41;;
vehicle.setSuspensionDamping&#40;dampValue * 2.0f * FastMath.sqrt&#40;stiffness&#41;&#41;;
vehicle.setSuspensionStiffness&#40;stiffness&#41;;
vehicle.setMaxSuspensionForce&#40;10000.0f&#41;;</pre>
<p>
We now have a node <code>vehicleNode</code> with a visible &quot;car&quot; geometry, which acts like a vehicle. One thing that&#039;s missing are wheels.
</p>
</div>
<h2><a>Adding the Wheels</a></h2>
<div>
<p>
We create four wheel Geometries and add them to the vehicle. Our wheel geometries are simple, non-physical discs (flat Cylinders), they are just visual decorations. Note that the physical wheel behaviour (the com.jme3.bullet.objects.VehicleWheel objects) is created internally by the <code>vehicle.addWheel()</code> method.
</p>
<p>
The <code>addWheel()</code> method sets following properties:
</p>
<ul>
<li><div> Vector3f connectionPoint – Coordinate where the suspension connects to the chassis (internally, this is where the Ray is casted downwards).</div>
</li>
<li><div> Vector3f direction – Wheel direction is typically a (0,-1,0) vector.</div>
</li>
<li><div> Vector3f axle – Axle direction is typically a (-1,0,0) vector.</div>
</li>
<li><div> float suspensionRestLength – Suspension rest length in world units</div>
</li>
<li><div> float wheelRadius – Wheel radius in world units</div>
</li>
<li><div> boolean isFrontWheel – Whether this wheel is one of the steering wheels. <br/>
Front wheels are the ones that rotate visibly when the vehicle turns.</div>
</li>
</ul>
<p>
We initialize a few variables that we will reuse when we add the four wheels. yOff, etc, are the particular wheel offsets for our small vehicle model.
</p>
<pre>Vector3f wheelDirection = new Vector3f&#40;0, -1, 0&#41;;
Vector3f wheelAxle = new Vector3f&#40;-1, 0, 0&#41;;
float radius = 0.5f;
float restLength = 0.3f;
float yOff = 0.5f;
float xOff = 1f;
float zOff = 2f;</pre><p> We create a Cylinder mesh shape that we use to create the four visible wheel geometries.</p><pre>Cylinder wheelMesh = new Cylinder&#40;16, 16, radius, radius * 0.6f, true&#41;;</pre><p> For each wheel, we create a Node and a Geometry. We attach the Cylinder Geometry to the Node. We rotate the wheel by 90° around the Y axis. We set a material to make it visible. Finally we add the wheel (plus its properties) to the vehicle.</p><pre>Node node1 = new Node&#40;&quot;wheel 1 node&quot;&#41;;
float zOff = 2f;</pre>
<p>
We create a Cylinder mesh shape that we use to create the four visible wheel geometries.
</p>
<pre>Cylinder wheelMesh = new Cylinder&#40;16, 16, radius, radius * 0.6f, true&#41;;</pre>
<p>
For each wheel, we create a Node and a Geometry. We attach the Cylinder Geometry to the Node. We rotate the wheel by 90° around the Y axis. We set a material to make it visible. Finally we add the wheel (plus its properties) to the vehicle.
</p>
<pre>Node node1 = new Node&#40;&quot;wheel 1 node&quot;&#41;;
Geometry wheels1 = new Geometry&#40;&quot;wheel 1&quot;, wheelMesh&#41;;
node1.attachChild&#40;wheels1&#41;;
wheels1.rotate&#40;0, FastMath.HALF_PI, 0&#41;;
wheels1.setMaterial&#40;mat&#41;;
&nbsp;
vehicle.addWheel&#40;node1, new Vector3f&#40;-xOff, yOff, zOff&#41;,
wheelDirection, wheelAxle, restLength, radius, true&#41;;</pre><p> The three next wheels are created in the same fashion, only the offsets are different. Remember to set the Boolean parameter correctly to indicate whether it&#039;s a front wheel.</p><pre>...
wheelDirection, wheelAxle, restLength, radius, true&#41;;</pre>
<p>
The three next wheels are created in the same fashion, only the offsets are different. Remember to set the Boolean parameter correctly to indicate whether it&#039;s a front wheel.
</p>
<pre>...
vehicle.addWheel&#40;node2, new Vector3f&#40;xOff, yOff, zOff&#41;,
wheelDirection, wheelAxle, restLength, radius, true&#41;;
...
@ -91,35 +209,60 @@ vehicle.addWheel&#40;node3, new Vector3f&#40;-xOff, yOff, -zOff&#41;,
wheelDirection, wheelAxle, restLength, radius, false&#41;;
...
vehicle.addWheel&#40;node4, new Vector3f&#40;xOff, yOff, -zOff&#41;,
wheelDirection, wheelAxle, restLength, radius, false&#41;;</pre><p> Attach the wheel Nodes to the vehicle Node to group them, so they move together.</p><pre>vehicleNode.attachChild&#40;node1&#41;;
wheelDirection, wheelAxle, restLength, radius, false&#41;;</pre>
<p>
Attach the wheel Nodes to the vehicle Node to group them, so they move together.
</p>
<pre>vehicleNode.attachChild&#40;node1&#41;;
vehicleNode.attachChild&#40;node2&#41;;
vehicleNode.attachChild&#40;node3&#41;;
vehicleNode.attachChild&#40;node4&#41;;</pre><p> As always, attach the vehicle Node to the rootNode to make it visible, and add the Vehicle Control to the PhysicsSpace to make the car physical.</p><pre>rootNode.attachChild&#40;vehicleNode&#41;;
getPhysicsSpace&#40;&#41;.add&#40;vehicle&#41;;</pre><p> Not shown here is that we also created a Material <code>mat</code>.</p></div><h2><a
name="steering_the_vehicle">Steering the Vehicle</a></h2><div
class="level2"><p> Not shown here is the standard way how we map the input keys to actions (see full code sample). Also refer to <a
href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">Input Handling</a>).</p><p> In the ActionListener, we implement the actions that control the vehicle&#039;s direction and speed. For the four directions (accelerate=up, brake=down, left, right), we specify how we want the vehicle to move.</p><ul><li
class="level1"><div
class="li"> The braking action is pretty straightforward: <br/> <code>vehicle.brake(brakeForce)</code></div></li><li
class="level1"><div
class="li"> For left and right turns, we add a constant to <code>steeringValue</code> when the key is pressed, and subtract it when the key is released. <br/> <code>vehicle.steer(steeringValue);</code></div></li><li
class="level1"><div
class="li"> For acceleration we add a constant to <code>accelerationValue</code> when the key is pressed, and substract it when the key is released. <br/> <code>vehicle.accelerate(accelerationValue);</code></div></li><li
class="level1"><div
class="li"> Because we can and it&#039;s fun, we also add a turbo booster that makes the vehicle jump when you press the assigned key (spacebar). <br/> <code>vehicle.applyImpulse(jumpForce, Vector3f.ZERO);</code></div></li></ul><pre>public void onAction&#40;String binding, boolean value, float tpf&#41; &#123;
vehicleNode.attachChild&#40;node4&#41;;</pre>
<p>
As always, attach the vehicle Node to the rootNode to make it visible, and add the Vehicle Control to the PhysicsSpace to make the car physical.
</p>
<pre>rootNode.attachChild&#40;vehicleNode&#41;;
getPhysicsSpace&#40;&#41;.add&#40;vehicle&#41;;</pre>
<p>
Not shown here is that we also created a Material <code>mat</code>.
</p>
</div>
<h2><a>Steering the Vehicle</a></h2>
<div>
<p>
Not shown here is the standard way how we map the input keys to actions (see full code sample). Also refer to <a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">Input Handling</a>).
</p>
<p>
In the ActionListener, we implement the actions that control the vehicle&#039;s direction and speed. For the four directions (accelerate=up, brake=down, left, right), we specify how we want the vehicle to move.
</p>
<ul>
<li><div> The braking action is pretty straightforward: <br/>
<code>vehicle.brake(brakeForce)</code></div>
</li>
<li><div> For left and right turns, we add a constant to <code>steeringValue</code> when the key is pressed, and subtract it when the key is released. <br/>
<code>vehicle.steer(steeringValue);</code></div>
</li>
<li><div> For acceleration we add a constant to <code>accelerationValue</code> when the key is pressed, and substract it when the key is released. <br/>
<code>vehicle.accelerate(accelerationValue);</code></div>
</li>
<li><div> Because we can and it&#039;s fun, we also add a turbo booster that makes the vehicle jump when you press the assigned key (spacebar). <br/>
<code>vehicle.applyImpulse(jumpForce, Vector3f.ZERO);</code></div>
</li>
</ul>
<pre>public void onAction&#40;String binding, boolean value, float tpf&#41; &#123;
if &#40;binding.equals&#40;&quot;Lefts&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123;
steeringValue += .5f;
&#125; else &#123;
steeringValue += -.5f;
&#125;
if &#40;value&#41; &#123; steeringValue += .5f; &#125; else &#123; steeringValue += -.5f; &#125;
vehicle.steer&#40;steeringValue&#41;;
&#125; else if &#40;binding.equals&#40;&quot;Rights&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123;
steeringValue += -.5f;
&#125; else &#123;
steeringValue += .5f;
&#125;
if &#40;value&#41; &#123; steeringValue += -.5f; &#125; else &#123; steeringValue += .5f; &#125;
vehicle.steer&#40;steeringValue&#41;;
&#125; else if &#40;binding.equals&#40;&quot;Ups&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123;
@ -129,11 +272,7 @@ class="li"> Because we can and it&#039;s fun, we also add a turbo booster that m
&#125;
vehicle.accelerate&#40;accelerationValue&#41;;
&#125; else if &#40;binding.equals&#40;&quot;Downs&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123;
vehicle.brake&#40;brakeForce&#41;;
&#125; else &#123;
vehicle.brake&#40;0f&#41;;
&#125;
if &#40;value&#41; &#123; vehicle.brake&#40;brakeForce&#41;; &#125; else &#123; vehicle.brake&#40;0f&#41;; &#125;
&#125; else if &#40;binding.equals&#40;&quot;Space&quot;&#41;&#41; &#123;
if &#40;value&#41; &#123;
vehicle.applyImpulse&#40;jumpForce, Vector3f.ZERO&#41;;
@ -149,20 +288,48 @@ class="li"> Because we can and it&#039;s fun, we also add a turbo booster that m
&#125; else &#123;
&#125;
&#125;
&#125;</pre><p> For your reference, this is how we initialized the constants for this example:</p><pre>private final float accelerationForce = 1000.0f;
&#125;</pre>
<p>
For your reference, this is how we initialized the constants for this example:
</p>
<pre>private final float accelerationForce = 1000.0f;
private final float brakeForce = 100.0f;
private float steeringValue = 0;
private float accelerationValue = 0;
private Vector3f jumpForce = new Vector3f&#40;0, 3000, 0&#41;;</pre><p> Remember, the standard input listener code that maps the actions to keys can be found in the code samples.</p></div><h2><a
name="detecting_collisions">Detecting Collisions</a></h2><div
class="level2"><p> Read the <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics#responding_to_a_physicscollisionevent.html">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions. You would do this if you want to react to collisions with custom events, such as adding points or substracting health.</p></div><h2><a
name="best_practices">Best Practices</a></h2><div
class="level2"><p> This example shows a very simple but functional vehicle. For a game you would implement steering behaviour and acceleration with values that are typical for the type of vehicle that you want to simulate. Instead of a box, you load a chassis model. You can consider using an <a
href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">AnalogListener</a> to respond to key events in a more sophisticated way.</p><p> For a more advanced example, look at <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java">TestFancyCar.java</a>.</p></div><div
class="footnotes"><div
class="fn"><sup><a
href="#fnt__1">1)</a></sup> <a
href="https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en">https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en</a></div></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:vehicles?do=export_xhtmlbody">view online version</a></em></p>
private Vector3f jumpForce = new Vector3f&#40;0, 3000, 0&#41;;</pre>
<p>
Remember, the standard input listener code that maps the actions to keys can be found in the code samples.
</p>
</div>
<h2><a>Detecting Collisions</a></h2>
<div>
<p>
Read the <a href="/com/jme3/gde/core/docs/jme3/advanced/physics#responding_to_a_physicscollisionevent.html">Responding to a PhysicsCollisionEvent</a> chapter in the general physics documentation on how to detect collisions. You would do this if you want to react to collisions with custom events, such as adding points or substracting health.
</p>
</div>
<h2><a>Best Practices</a></h2>
<div>
<p>
This example shows a very simple but functional vehicle. For a game you would implement steering behaviour and acceleration with values that are typical for the type of vehicle that you want to simulate. Instead of a box, you load a chassis model. You can consider using an <a href="/com/jme3/gde/core/docs/jme3/advanced/input_handling.html">AnalogListener</a> to respond to key events in a more sophisticated way.
</p>
<p>
For a more advanced example, look at <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestFancyCar.java"><param name="text" value="<html><u>TestFancyCar.java</u></html>"><param name="textColor" value="blue"></object>.
</p>
</div>
<div>
<div><sup><a href="#fnt__1">1)</a></sup>
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en"><param name="text" value="<html><u>https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&amp;hl=en</u></html>"><param name="textColor" value="blue"></object> </div>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:vehicles?do=export_xhtmlbody">view online version</a></em></p>

@ -1,72 +1,339 @@
<h1><a
name="walking_character">Walking Character</a></h1><div
class="level1"><p> <strong>Work in progress.</strong></p><p> In other code samples we have seen how to create collidable landscapes and walk around in a first-person perspective, by enclosing the camera with a collision shape.</p><p> Many games however require a third-person perspective of the character. If you load a character model, create a PhysicsControl for it, and use forces to push it around, you may not get the desired effect: Phyical objects often fall over when pushed, and that is not what you expect of a walking character.</p><p> This is why jME3 offers a special CharacterControl to implement walking characters.</p></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><p> The full code sample can be found here:</p><ul><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java">TestPhysicsCharacter.java</a> (third-person view)</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java">TestWalkingChar.java</a> (third-person view)</div></li><li
class="level1"><div
class="li"> <a
href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestQ3.java">TestQ3.java</a> (first-person view)</div></li></ul></div><h2><a
name="overview_of_this_physics_application">Overview of this Physics Application</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Create a SimpleApplication with a <a
href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a></div><ul><li
class="level2"><div
class="li"> This gives us a Physics Space</div></li></ul></li><li
class="level1"><div
class="li"> Load any physical game level model, terrain, or floor</div></li><li
class="level1"><div
class="li"> Load an animated character model</div></li><li
class="level1"><div
class="li"> Set up animation channel and controller</div></li><li
class="level1"><div
class="li"> Add a CharacterControl to the model</div></li></ol></div><h2><a
name="creating_the_character">Creating the Character</a></h2><div
class="level2"><ol><li
class="level1"><div
class="li"> Initialze physical character behaviour, including collision shape</div><ol><li
class="level2"><div
class="li"> Create CapsuleCollisionShape of the right size for the model.</div><ul><li
class="level3"><div
class="li"> A Capsule is a cylinder with rounded top and bottom: A good collision shape for a character since it reduces the risk of getting stuck on obstacles.</div></li></ul></li><li
class="level2"><div
class="li"> Create a CharacterControl from the collision shape</div></li></ol></li><li
class="level1"><div
class="li"> Load the visible character model, and add the physical behaviour to it</div><ol><li
class="level2"><div
class="li"> Load an animated model (e.g. &quot;Models/Oto/Oto.mesh.xml&quot;).</div></li><li
class="level2"><div
class="li"> Add the CharacterControl to the character model.</div></li></ol></li><li
class="level1"><div
class="li"> Make character visible and physical</div><ol><li
class="level2"><div
class="li"> Attach the model to the rootNode to make it appear in the scene.</div></li><li
class="level2"><div
class="li"> Add the CharacterControl to the PhysicsSpace to make it physical.</div></li></ol></li></ol><pre>// initialze physical character behaviour, including collision shape
CapsuleCollisionShape capsule = new CapsuleCollisionShape&#40;3f, 4f&#41;;
CharacterControl character = new CharacterControl&#40;capsule, 0.01f&#41;;
// load the visible character model and add the physical behaviour to it
Node model = &#40;Node&#41; assetManager.loadModel&#40;&quot;Models/Oto/Oto.mesh.xml&quot;&#41;;
model.addControl&#40;character&#41;;
// Make character visible and physical
rootNode.attachChild&#40;model&#41;; // make it visible
getPhysicsSpace&#40;&#41;.add&#40;character&#41;; // make it physical</pre></div><h2><a
name="setting_up_the_animation_controller">Setting Up the Animation Controller</a></h2><div
class="level2"><p> We create two AninChannels, for example one for walking, one for shooting. The shootingChannel only controls one arm, while the walking channels controls the whole animation.</p><pre>AnimControl animationControl = model.getControl&#40;AnimControl.class&#41;;
animationControl.addListener&#40;this&#41;;
&nbsp;
AnimChannel animationChannel = animationControl.createChannel&#40;&#41;;
AnimChannel shootingChannel = animationControl.createChannel&#40;&#41;;
&nbsp;
shootingChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;uparm.right&quot;&#41;&#41;;
shootingChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;arm.right&quot;&#41;&#41;;
shootingChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;hand.right&quot;&#41;&#41;;</pre><p> The extra shooting channel exists so the character can lift an arm to shoot and walk at the same time.</p></div><h2><a
name="walking">Walking</a></h2><div
class="level2"><p> Work in progress (this is being updated for the new physics and chase cam.)</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:walking_character?do=export_xhtmlbody">view online version</a></em></p>
<h1><a>Walking Character</a></h1>
<div>
<p>
In the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestQ3.java"><param name="text" value="<html><u>TestQ3.java</u></html>"><param name="textColor" value="blue"></object> code sample you have seen how to create collidable landscapes and walk around in a first-person perspective, where the camera is enclosed by a collision shape. Other games however require a third-person perspective of the character: In these cases you use a CharacterControl. This example uses a custom navigation – press WASD to walk and drag the mouse to rotate.
</p>
</div>
<h3><a>Why use CharacterControl instead of RigidBodyControl?</a></h3>
<div>
<p>
When you load a character model with a RigidBodyControl, and use forces to push it around, you do not get the desired effect: RigidBodyControl&#039;ed objects can tip over when pushed, and that is not what you expect of a walking character. jMonkeyEngine offers a special CharacterControl with a special walking methods to implement characters that walk upright.
</p>
</div>
<h3><a>Sample Code</a></h3>
<div>
<p>
The several related code samples can be found here:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java"><param name="text" value="<html><u>TestPhysicsCharacter.java</u></html>"><param name="textColor" value="blue"></object> (third-person view)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java"><param name="text" value="<html><u>TestWalkingChar.java</u></html>"><param name="textColor" value="blue"></object> (third-person view)</div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestQ3.java"><param name="text" value="<html><u>TestQ3.java</u></html>"><param name="textColor" value="blue"></object> (first-person view)</div>
</li>
</ul>
<p>
The code in this tutorial is a combination of them.
</p>
</div>
<h3><a>Code Skeleton</a></h3>
<div>
<pre>public class WalkingCharacterDemo extends SimpleApplication
implements ActionListener, AnimEventListener &#123;
public static void main&#40;String&#91;&#93; args&#41; &#123;
WalkingCharacterDemo app = new WalkingCharacterDemo&#40;&#41;;
app.start&#40;&#41;;
&#125;
public void simpleInitApp&#40;&#41; &#123; &#125;
public void simpleUpdate&#40;float tpf&#41; &#123; &#125;
public void onAction&#40;String name, boolean isPressed, float tpf&#41; &#123; &#125;
public void onAnimCycleDone&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123; &#125;
public void onAnimChange&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123; &#125;</pre>
</div>
<h3><a>Overview</a></h3>
<div>
<ol>
<li><div> Activate physics by adding a <a href="/com/jme3/gde/core/docs/jme3/advanced/physics.html">BulletAppState</a>.</div>
</li>
<li><div> Init the scene by loading a game level model (terrain or floor/buildings) and giving it a MeshCollisionShape.</div>
</li>
<li><div> Create the animated character</div>
<ol>
<li><div> Load an animated character model.</div>
</li>
<li><div> Add a CharacterControl to the model.</div>
</li>
</ol>
</li>
<li><div> Set up animation channel and controllers.</div>
</li>
<li><div> Add a ChaseCam or CameraNode.</div>
</li>
<li><div> Handle navigational inputs</div>
</li>
</ol>
</div>
<h2><a>Activate Physics</a></h2>
<div>
<pre>private BulletAppState bulletAppState;
...
public void simpleInitApp&#40;&#41; &#123;
bulletAppState = new BulletAppState&#40;&#41;;
//bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
stateManager.attach&#40;bulletAppState&#41;;
...
&#125;</pre>
</div>
<h2><a>Initialize the Scene</a></h2>
<div>
<p>
In the simpleInitApp() method you initialize the scene and give it a MeshCollisionShape. The sample in the jme3 sources uses a custom helper class that simply creates a flat floor and drops some cubes and spheres on it:
</p>
<pre>public void simpleInitApp&#40;&#41; &#123;
...
PhysicsTestHelper.createPhysicsTestWorld&#40;rootNode,
assetManager, bulletAppState.getPhysicsSpace&#40;&#41;&#41;;
...</pre>
<p>
In a real game, you would load a scene model here instead of a test world. You can load a model from a local or remote zip file, and scale and position it:
</p>
<pre>private Node gameLevel;
..
public void simpleInitApp&#40;&#41; &#123;
...
//assetManager.registerLocator(&quot;quake3level.zip&quot;, ZipLocator.class.getName());
assetManager.registerLocator&#40;
&quot;http://jmonkeyengine.googlecode.com/files/quake3level.zip&quot;,
HttpZipLocator.class.getName&#40;&#41;&#41;;
MaterialList matList = &#40;MaterialList&#41; assetManager.loadAsset&#40;&quot;Scene.material&quot;&#41;;
OgreMeshKey key = new OgreMeshKey&#40;&quot;main.meshxml&quot;, matList&#41;;
gameLevel = &#40;Node&#41; assetManager.loadAsset&#40;key&#41;;
gameLevel.setLocalTranslation&#40;-20, -16, 20&#41;;
gameLevel.setLocalScale&#40;0.10f&#41;;
gameLevel.addControl&#40;new RigidBodyControl&#40;0&#41;&#41;;
rootNode.attachChild&#40;gameLevel&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.addAll&#40;gameLevel&#41;;
...</pre>
<p>
Also, add a light source to be able to see the scene.
</p>
<pre> AmbientLight light = new AmbientLight&#40;&#41;;
light.setColor&#40;ColorRGBA.White.mult&#40;2&#41;&#41;;
rootNode.addLight&#40;light&#41;;</pre>
</div>
<h2><a>Create the Animated Character</a></h2>
<div>
<p>
You create an animated model, such as Oto.mesh.xml.
</p>
<ol>
<li><div> Place the &quot;Oto&quot; model into the <code>assets/Models/Oto/</code> directory of your project.</div>
</li>
<li><div> Create the CollisionShape and adjust the capsule radius and height to fit your character model.</div>
</li>
<li><div> Create the CharacterControl and adjust the stepheight (here 0.05f) to the height that the character can climb up without jumping.</div>
</li>
<li><div> Load the visible model. Make sure its start position does not overlap with scene objects.</div>
</li>
<li><div> Add the CharacterControl to the model and register it to the physicsSpace.</div>
</li>
<li><div> Attach the visible model to the rootNode.</div>
</li>
</ol>
<pre>private CharacterControl character;
private Node model;
...
public void simpleInitApp&#40;&#41; &#123;
...
CapsuleCollisionShape capsule = new CapsuleCollisionShape&#40;3f, 4f&#41;;
character = new CharacterControl&#40;capsule, 0.05f&#41;;
character.setJumpSpeed&#40;20f&#41;;
model = &#40;Node&#41; assetManager.loadModel&#40;&quot;Models/Oto/Oto.mesh.xml&quot;&#41;;
model.addControl&#40;character&#41;;
bulletAppState.getPhysicsSpace&#40;&#41;.add&#40;character&#41;;
rootNode.attachChild&#40;model&#41;;
...</pre>
<p>
<br/>
<strong>Did you know?</strong> A CapsuleCollisionShape is a cylinder with rounded top and bottom. A capsule rotated upright is a good collision shape for a humanoid character since its roundedness reduces the risk of getting stuck on obstacles.
</p>
</div>
<h3><a>Set Up AnimControl and AnimChannels</a></h3>
<div>
<p>
Create several AnimChannels, one for each animation that can happen simultaneously. In this example, you create one channel for walking and one for attacking. (Because the character can attack with its arms and walk with the rest of the body at the same time.)
</p>
<pre>private AnimChannel animationChannel;
private AnimChannel attackChannel;
private AnimControl animationControl;
...
public void simpleInitApp&#40;&#41; &#123;
...
animationControl = model.getControl&#40;AnimControl.class&#41;;
animationControl.addListener&#40;this&#41;;
animationChannel = animationControl.createChannel&#40;&#41;;
attackChannel = animationControl.createChannel&#40;&#41;;
attackChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;uparm.right&quot;&#41;&#41;;
attackChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;arm.right&quot;&#41;&#41;;
attackChannel.addBone&#40;animationControl.getSkeleton&#40;&#41;.getBone&#40;&quot;hand.right&quot;&#41;&#41;;
...</pre>
<p>
The attackChannel only controls one arm, while the walking channels controls the whole character.
</p>
</div>
<h2><a>Add ChaseCam / CameraNode</a></h2>
<div>
<pre>private ChaseCamera chaseCam;
...
public void simpleInitApp&#40;&#41; &#123;
...
flyCam.setEnabled&#40;false&#41;;
chaseCam = new ChaseCamera&#40;cam, model, inputManager&#41;;
...</pre>
</div>
<h2><a>Handle navigational inputs</a></h2>
<div>
<p>
Configure custom key bindings for WASD keys that you will use to make the character walk.
</p>
<pre>private boolean left = false, right = false, up = false, down = false;
...
public void simpleInitApp&#40;&#41; &#123;
...
inputManager.addMapping&#40;&quot;CharLeft&quot;, new KeyTrigger&#40;KeyInput.KEY_A&#41;&#41;;
inputManager.addMapping&#40;&quot;CharRight&quot;, new KeyTrigger&#40;KeyInput.KEY_D&#41;&#41;;
inputManager.addMapping&#40;&quot;CharForward&quot;, new KeyTrigger&#40;KeyInput.KEY_W&#41;&#41;;
inputManager.addMapping&#40;&quot;CharBackward&quot;, new KeyTrigger&#40;KeyInput.KEY_S&#41;&#41;;
inputManager.addMapping&#40;&quot;CharJump&quot;, new KeyTrigger&#40;KeyInput.KEY_RETURN&#41;&#41;;
inputManager.addMapping&#40;&quot;CharAttack&quot;, new KeyTrigger&#40;KeyInput.KEY_SPACE&#41;&#41;;
inputManager.addListener&#40;this, &quot;CharLeft&quot;, &quot;CharRight&quot;&#41;;
inputManager.addListener&#40;this, &quot;CharForward&quot;, &quot;CharBackward&quot;&#41;;
inputManager.addListener&#40;this, &quot;CharJump&quot;, &quot;CharAttack&quot;&#41;;
...
&#125;</pre>
<p>
Respond to the key bindings by setting variables that track in which direction you will go. (No actual walking happens here yet)
</p>
<pre>@Override
public void onAction&#40;String binding, boolean value, float tpf&#41; &#123;
if &#40;binding.equals&#40;&quot;CharLeft&quot;&#41;&#41; &#123;
if &#40;value&#41; left = true;
else left = false;
&#125; else if &#40;binding.equals&#40;&quot;CharRight&quot;&#41;&#41; &#123;
if &#40;value&#41; right = true;
else right = false;
&#125; else if &#40;binding.equals&#40;&quot;CharForward&quot;&#41;&#41; &#123;
if &#40;value&#41; up = true;
else up = false;
&#125; else if &#40;binding.equals&#40;&quot;CharBackward&quot;&#41;&#41; &#123;
if &#40;value&#41; down = true;
else down = false;
&#125; else if &#40;binding.equals&#40;&quot;CharJump&quot;&#41;&#41;
character.jump&#40;&#41;;
if &#40;binding.equals&#40;&quot;CharAttack&quot;&#41;&#41;
attack&#40;&#41;;
&#125;</pre>
<p>
The player can attack and walk at the same time. Attack() is a custom method that triggers an attack animation in the arms. Here you should also add custom code to play an effect and sound, and to determine whether the hit was successful.
</p>
<pre>private void attack&#40;&#41; &#123;
attackChannel.setAnim&#40;&quot;Dodge&quot;, 0.1f&#41;;
attackChannel.setLoopMode&#40;LoopMode.DontLoop&#41;;
&#125;</pre>
<p>
The update loop looks at the directional variables and moves the character accordingly. Since it&#039;s a physical character, we use setWalkDirection(). The variable airTime tracks how long the character is off the ground (e.g. when jumping or falling) and adjusts the walk and stand animations acccordingly.
</p>
<pre>private Vector3f walkDirection = new Vector3f&#40;0,0,0&#41;;
private float airTime = 0;
public void simpleUpdate&#40;float tpf&#41; &#123;
Vector3f camDir = cam.getDirection&#40;&#41;.clone&#40;&#41;.multLocal&#40;0.25f&#41;;
Vector3f camLeft = cam.getLeft&#40;&#41;.clone&#40;&#41;.multLocal&#40;0.25f&#41;;
camDir.y = 0;
camLeft.y = 0;
walkDirection.set&#40;0, 0, 0&#41;;
if &#40;left&#41; walkDirection.addLocal&#40;camLeft&#41;;
if &#40;right&#41; walkDirection.addLocal&#40;camLeft.negate&#40;&#41;&#41;;
if &#40;up&#41; walkDirection.addLocal&#40;camDir&#41;;
if &#40;down&#41; walkDirection.addLocal&#40;camDir.negate&#40;&#41;&#41;;
if &#40;!character.onGround&#40;&#41;&#41; &#123;
airTime = airTime + tpf;
&#125; else &#123;
airTime = 0;
&#125;
if &#40;walkDirection.length&#40;&#41; == 0&#41; &#123;
if &#40;!&quot;stand&quot;.equals&#40;animationChannel.getAnimationName&#40;&#41;&#41;&#41; &#123;
animationChannel.setAnim&#40;&quot;stand&quot;, 1f&#41;;
&#125;
&#125; else &#123;
character.setViewDirection&#40;walkDirection&#41;;
if &#40;airTime &gt; .3f&#41; &#123;
if &#40;!&quot;stand&quot;.equals&#40;animationChannel.getAnimationName&#40;&#41;&#41;&#41; &#123;
animationChannel.setAnim&#40;&quot;stand&quot;&#41;;
&#125;
&#125; else if &#40;!&quot;Walk&quot;.equals&#40;animationChannel.getAnimationName&#40;&#41;&#41;&#41; &#123;
animationChannel.setAnim&#40;&quot;Walk&quot;, 0.7f&#41;;
&#125;
&#125;
character.setWalkDirection&#40;walkDirection&#41;;
&#125;</pre>
<p>
This method resets the walk animation.
</p>
<pre>public void onAnimCycleDone&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123;
if &#40;channel == attackChannel&#41; channel.setAnim&#40;&quot;stand&quot;&#41;;
&#125;
public void onAnimChange&#40;AnimControl control, AnimChannel channel, String animName&#41; &#123; &#125;</pre>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:walking_character?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 163 KiB

@ -1,80 +1,139 @@
<h1><a
name="seamonkey_-_jme3_water_system">SeaMonkey - jME3 Water System</a></h1><div
class="level1"><p> <strong>DRAFT</strong></p><p> Here is some background info for JME3&#039;s frist water implementation, nicknamed SeaMonkey:</p><ul><li
class="level1"><div
class="li"> <a
href="http://www.jmonkeyengine.com/forum/index.php?topic=14740.0">http://www.jmonkeyengine.com/forum/index.php?topic=14740.0</a></div></li><li
class="level1"><div
class="li"> <a
href="http://www.bonzaisoftware.com/water_tut.html">http://www.bonzaisoftware.com/water_tut.html</a></div></li><li
class="level1"><div
class="li"> <a
href="http://www.gametutorials.com/Articles/RealisticWater.pdf">http://www.gametutorials.com/Articles/RealisticWater.pdf</a></div></li></ul><p> <a
href="/wiki/lib/exe/fetch.php?hash=af543c&amp;media=http%3A%2F%2Fwww.jmonkeyengine.com%2Fwp-content%2Fuploads%2F2010%2F10%2Fsimplewaterdemo.jpg"><img
src="/wiki/lib/exe/fetch.php?hash=af543c&amp;w=277&amp;h=180&amp;media=http%3A%2F%2Fwww.jmonkeyengine.com%2Fwp-content%2Fuploads%2F2010%2F10%2Fsimplewaterdemo.jpg" class="mediacenter" title="www.jmonkeyengine.com_wp-content_uploads_2010_10_simplewaterdemo.jpg" alt="www.jmonkeyengine.com_wp-content_uploads_2010_10_simplewaterdemo.jpg" width="277" height="180" /></a></p></div><h2><a
name="simplewaterprocessor">SimpleWaterProcessor</a></h2><div
class="level2"><p> A JME3 scene with water uses a <code>com.jme3.water.SimpleWaterProcessor</code> (which implements the SceneProcessor interface).</p><p> To achieve a water effect, JME3 uses shaders and a special material, <code>Common/MatDefs/Water/SimpleWater.j3md</code>. The water surface is a quad, and we use normal map and dU/dV map texturing to simulate the waves.</p><ol><li
class="level1"><div
class="li"> Every frame, we render to three texture maps:</div><ul><li
class="level2"><div
class="li"> For the water surface (reflection), we take a snapshot of the environment, flip it upside down, and clip it to the visible water surface. Note that we do not actually use a &quot;water texture&quot; color map: The &quot;texture&quot; of the water is solely a distorted reflection.</div></li><li
class="level2"><div
class="li"> For the &quot;wavy&quot; distortion (refraction), we use the derivative of a normal map, a dU/dV map.</div></li><li
class="level2"><div
class="li"> For the fogginess of water (depth) we use a depth map from the terrains z-buffer.</div></li></ul></li><li
class="level1"><div
class="li"> In the shaders, we add all of the texture maps together.</div><ul><li
class="level2"><div
class="li"> For the &quot;bumpy&quot; displacement of the waves, we use a normal map and a du/dv map that are shifted against each other over time to create the wave effect.</div></li><li
class="level2"><div
class="li"> For the light reflection vectors on the water surface, we use the Fresnel formula, together with normal vectors.</div></li><li
class="level2"><div
class="li"> We add specular lighting.</div></li></ul></li><li
class="level1"><div
class="li"> (For the underwater caustics effect, we use splatted textures. – TODO)</div></li></ol></div><h2><a
name="usage">Usage</a></h2><div
class="level2"><p> <a
href="/wiki/lib/exe/detail.php/jme3:advanced:simplewater.png?id=jme3%3Aadvanced%3Awater"><img
src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/simplewater.png?w=384&amp;h=288" class="mediaright" align="right" alt="" width="384" height="288" /></a></p><ol><li
class="level1"><div
class="li"> Create a <code>mainScene</code> Node</div><ol><li
class="level2"><div
class="li"> Attach the <code>mainScene</code> Node to the <code>rootNode</code></div></li></ol></li><li
class="level1"><div
class="li"> Load your <code>scene</code> Spatial</div><ol><li
class="level2"><div
class="li"> Add a light source to the <code>scene</code> Spatial</div></li><li
class="level2"><div
class="li"> Attach the <code>scene</code> Spatial to the <code>mainScene</code> Node</div></li></ol></li><li
class="level1"><div
class="li"> Load your <a
href="/com/jme3/gde/core/docs/jme3/advanced/sky.html">sky</a> Geometry</div><ol><li
class="level2"><div
class="li"> Attach the sky Geometry to the <code>mainScene</code> Node</div></li></ol></li><li
class="level1"><div
class="li"> Create the SimpleWaterProcessor <code>waterProcessor</code></div><ol><li
class="level2"><div
class="li"> Set the processor&#039;s ReflectionScene to the <code>mainScene</code> Spatial (!)</div></li><li
class="level2"><div
class="li"> Set the processor&#039;s Plane to where you want your water surface to be</div></li><li
class="level2"><div
class="li"> Set the processor&#039;s WaterDepth, DistortionScale, and WaveSpeed</div></li><li
class="level2"><div
class="li"> Attach the processor to the <code>viewPort</code></div></li></ol></li><li
class="level1"><div
class="li"> Create a Quad <code>quad</code></div><ol><li
class="level2"><div
class="li"> Set the quad&#039;s TextureCoordinates to specify the size of the waves</div></li></ol></li><li
class="level1"><div
class="li"> Create a <code>water</code> Geometry from the Quad</div><ol><li
class="level2"><div
class="li"> Set the water&#039;s translation and rotation (same Y value as Plane above!)</div></li><li
class="level2"><div
class="li"> Set the water&#039;s material to the processor&#039;s output material</div></li><li
class="level2"><div
class="li"> Attach the <code>water</code> Geometry to the <code>rootNode</code>. (Not to the mainScene!)</div></li></ol></li></ol></div><h2><a
name="sample_code">Sample Code</a></h2><div
class="level2"><p> The sample code can be found in <code>jme3/src/jme3test/water/TestSimpleWater.java</code> and <code>jme3/src/jme3test/water/TestSceneWater.java</code>.</p><p> Here is the most important part of the code:</p><pre>// we create a water processor
<h1><a>Simple Water</a></h1>
<div>
<p>
Here is some background info for JME3&#039;s basic water implementation:
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.jmonkeyengine.com/forum/index.php?topic=14740.0"><param name="text" value="<html><u>http://www.jmonkeyengine.com/forum/index.php?topic=14740.0</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.bonzaisoftware.com/water_tut.html"><param name="text" value="<html><u>http://www.bonzaisoftware.com/water_tut.html</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.gametutorials.com/Articles/RealisticWater.pdf"><param name="text" value="<html><u>http://www.gametutorials.com/Articles/RealisticWater.pdf</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
<p>
<img src="/wiki/lib/exe/fetch.php">
</p>
</div>
<h2><a>SimpleWaterProcessor</a></h2>
<div>
<p>
A JME3 scene with water can use a <code>com.jme3.water.SimpleWaterProcessor</code> (which implements the SceneProcessor interface).
</p>
<p>
To achieve a water effect, JME3 uses shaders and a special material, <code>Common/MatDefs/Water/SimpleWater.j3md</code>. The water surface is a quad, and we use normal map and dU/dV map texturing to simulate the waves.
</p>
<ol>
<li><div> Every frame, we render to three texture maps:</div>
<ul>
<li><div> For the water surface (reflection), we take a snapshot of the environment, flip it upside down, and clip it to the visible water surface. Note that we do not actually use a &quot;water texture&quot; color map: The &quot;texture&quot; of the water is solely a distorted reflection.</div>
</li>
<li><div> For the &quot;wavy&quot; distortion (refraction), we use the derivative of a normal map, a dU/dV map.</div>
</li>
<li><div> For the fogginess of water (depth) we use a depth map from the terrains z-buffer.</div>
</li>
</ul>
</li>
<li><div> In the shaders, we add all of the texture maps together. </div>
<ul>
<li><div> For the &quot;bumpy&quot; displacement of the waves, we use a normal map and a du/dv map that are shifted against each other over time to create the wave effect.</div>
</li>
<li><div> For the light reflection vectors on the water surface, we use the Fresnel formula, together with normal vectors.</div>
</li>
<li><div> We add specular lighting.</div>
</li>
</ul>
</li>
<li><div> (For the underwater caustics effect, we use splatted textures. – WIP/TODO)</div>
</li>
</ol>
</div>
<h2><a>Usage</a></h2>
<div>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/advanced/simplewater.png">
</p>
<ol>
<li><div> Create a <code>mainScene</code> Node</div>
<ol>
<li><div> Attach the <code>mainScene</code> Node to the <code>rootNode</code></div>
</li>
</ol>
</li>
<li><div> Load your <code>scene</code> Spatial</div>
<ol>
<li><div> Add a light source to the <code>scene</code> Spatial</div>
</li>
<li><div> Attach the <code>scene</code> Spatial to the <code>mainScene</code> Node</div>
</li>
</ol>
</li>
<li><div> Load your <a href="/com/jme3/gde/core/docs/jme3/advanced/sky.html">sky</a> Geometry</div>
<ol>
<li><div> Attach the sky Geometry to the <code>mainScene</code> Node</div>
</li>
</ol>
</li>
<li><div> Create the SimpleWaterProcessor <code>waterProcessor</code></div>
<ol>
<li><div> Set the processor&#039;s ReflectionScene to the <code>mainScene</code> Spatial (!)</div>
</li>
<li><div> Set the processor&#039;s Plane to where you want your water surface to be</div>
</li>
<li><div> Set the processor&#039;s WaterDepth, DistortionScale, and WaveSpeed</div>
</li>
<li><div> Attach the processor to the <code>viewPort</code></div>
</li>
</ol>
</li>
<li><div> Create a Quad <code>quad</code></div>
<ol>
<li><div> Set the quad&#039;s TextureCoordinates to specify the size of the waves</div>
</li>
</ol>
</li>
<li><div> Create a <code>water</code> Geometry from the Quad</div>
<ol>
<li><div> Set the water&#039;s translation and rotation (same Y value as Plane above!)</div>
</li>
<li><div> Set the water&#039;s material to the processor&#039;s output material</div>
</li>
<li><div> Attach the <code>water</code> Geometry to the <code>rootNode</code>. (Not to the mainScene!)</div>
</li>
</ol>
</li>
</ol>
</div>
<h2><a>Sample Code</a></h2>
<div>
<p>
The sample code can be found in <code>jme3/src/jme3test/water/TestSimpleWater.java</code> and <code>jme3/src/jme3test/water/TestSceneWater.java</code>.
</p>
<p>
Here is the most important part of the code:
</p>
<pre>// we create a water processor
SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor&#40;assetManager&#41;;
waterProcessor.setReflectionScene&#40;mainScene&#41;;
&nbsp;
@ -98,9 +157,56 @@ water.setLocalRotation&#40;new Quaternion&#40;&#41;.fromAngleAxis&#40;-FastMath.
water.setLocalTranslation&#40;-200, -6, 250&#41;;
water.setShadowMode&#40;ShadowMode.Receive&#41;;
water.setMaterial&#40;waterProcessor.getMaterial&#40;&#41;&#41;;
rootNode.attachChild&#40;water&#41;;</pre></div><h2><a
name="settings">Settings</a></h2><div
class="level2"><p> You can lower the render size to gain higher performance:</p><pre>waterProcessor.setRenderSize&#40;128,128&#41;;</pre><p> The deeper the water, the more transparent. (?)</p><pre>waterProcessor.setWaterDepth&#40;40&#41;;</pre><p> A higher distortion scale makes bigger waves.</p><pre>waterProcessor.setDistortionScale&#40;0.05f&#41;;</pre><p> A lower wave speed makes calmer water.</p><pre>waterProcessor.setWaveSpeed&#40;0.05f&#41;;</pre><p> If your scene does not have a lightsource, you can set the light direction for the water:</p><pre>waterProcessor.setLightDirection&#40; new Vector3f&#40;0.55f, -0.82f, 0.15f&#41;&#41;;</pre><p> Instead of creating a quad and specifying a plane, you can get a default waterplane from the processor:</p><pre>Geometry waterPlane = waterProcessor.createWaterGeometry&#40;10, 10&#41;;
rootNode.attachChild&#40;water&#41;;</pre>
</div>
<h2><a>Settings</a></h2>
<div>
<p>
You can lower the render size to gain higher performance:
</p>
<pre>waterProcessor.setRenderSize&#40;128,128&#41;;</pre>
<p>
The deeper the water, the more transparent. (?)
</p>
<pre>waterProcessor.setWaterDepth&#40;40&#41;;</pre>
<p>
A higher distortion scale makes bigger waves.
</p>
<pre>waterProcessor.setDistortionScale&#40;0.05f&#41;;</pre>
<p>
A lower wave speed makes calmer water.
</p>
<pre>waterProcessor.setWaveSpeed&#40;0.05f&#41;;</pre>
<p>
If your scene does not have a lightsource, you can set the light direction for the water:
</p>
<pre>waterProcessor.setLightDirection&#40; new Vector3f&#40;0.55f, -0.82f, 0.15f&#41;&#41;;</pre>
<p>
Instead of creating a quad and specifying a plane, you can get a default waterplane from the processor:
</p>
<pre>Geometry waterPlane = waterProcessor.createWaterGeometry&#40;10, 10&#41;;
waterPlane.setLocalTranslation&#40;-5, 0, 5&#41;;
waterPlane.setMaterial&#40;waterProcessor.getMaterial&#40;&#41;&#41;;</pre><p> You can offer a switch to set the water Material to a static texture – for users with slow PCs.</p></div>
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:water?do=export_xhtmlbody">view online version</a></em></p>
waterPlane.setMaterial&#40;waterProcessor.getMaterial&#40;&#41;&#41;;</pre>
<p>
You can offer a switch to set the water Material to a static texture – for users with slow PCs.
</p>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:advanced:water?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

@ -0,0 +1,250 @@
<h1><a>Android Support in the jMonkeyEngine</a></h1>
<div>
<p>
This is a draft of a feature that is work in progress. If you have questions or suggestions, please leave a comment on the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/android/forum/topic/android-deployment-via-checkbox-is-here"><param name="text" value="<html><u>Android forum thread</u></html>"><param name="textColor" value="blue"></object>!
</p>
</div>
<h2><a>Requirements</a></h2>
<div>
<ul>
<li><div> Android device that supports OpenGL ES 2.0</div>
</li>
<li><div> Install <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://developer.android.com/sdk/index.html"><param name="text" value="<html><u>Android SDK 2.2</u></html>"><param name="textColor" value="blue"></object> or better.</div>
</li>
<li><div> Install jMonkeyPlatform</div>
</li>
<li><div> Install Android Project support in the jMonkeyPlatform:</div>
<ol>
<li><div> Open Tools→Plugins→Settings</div>
</li>
<li><div> Activate the nightly build.</div>
</li>
<li><div> Go to Tools→Plugins→Available Plugins.</div>
</li>
<li><div> Install the Android Support plugin.</div>
</li>
</ol>
</li>
</ul>
</div>
<h2><a>Features</a></h2>
<div>
</div>
<h3><a>JMonkeyEngine3 Android Integration</a></h3>
<div>
<ul>
<li><div> Android touch events are translated into mouse events.</div>
</li>
<li><div> No more unhandled exceptions (i.e. no more black screens)</div>
</li>
<li><div> Lifecycle management</div>
<ul>
<li><div> Leaving the activity with the Back key destroys the app (quit).</div>
</li>
<li><div> Leaving the activity with the Home key freezes the app in the background. When you return, the app is in the same state as when you left it (pause).</div>
</li>
</ul>
</li>
<li><div> Currently supports all jmetests except:</div>
<ul>
<li><div> Framebuffers - WIP</div>
</li>
<li><div> Shadows - WIP</div>
</li>
<li><div> Water - not tested yet</div>
</li>
</ul>
</li>
</ul>
</div>
<h3><a>jMonkeyPlatform Android Integration</a></h3>
<div>
<p>
Mobile deployment is a &quot;one-click&quot; option next to Desktop/WebStart/Applet deployment in the jMonkeyPlatform.
</p>
<ul>
<li><div> Automatic creation of Android harness and settings.</div>
</li>
<li><div> Ant script build target creates APK file.</div>
</li>
<li><div> Ant script run target executes APK on Android Emulator or mobile device.</div>
</li>
</ul>
</div>
<h2><a>Beta Instructions</a></h2>
<div>
<ol>
<li><div> Make sure you have installed the Android Project Support into the jMonkeyPlatform.</div>
</li>
<li><div> Open the jMonkeyPlatform Options&gt;Mobile and enter the path to your Android <acronym title="Software Development Kit">SDK</acronym> directory, and click OK. E.g. <code>/opt/android-sdk</code></div>
</li>
</ol>
</div>
<h4><a>Activate Android Deployment</a></h4>
<div>
<ol>
<li><div> Open an existing JME3 project, or create a new JME3 project.</div>
</li>
<li><div> Right-click the project node in the Projects Window and open the Properties.</div>
</li>
<li><div> In the Application&gt;Mobile Properties, enable Mobile Deployment, and select an Android target. <br/>
This creates a &quot;mobile&quot; folder in your projects directory. This folder contains a complete android project with correct settings to run the application using the AndroidHarness.</div>
</li>
<li><div> (Restart the jMonkeyEngine)</div>
</li>
<li><div> A Mobile Files node appears in the Project window. <br/>
It lets you edit the MainActivitity.java, the AndroidManifest.xml, and build.properties.</div>
</li>
</ol>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/nvyyd.png">
</p>
<p>
The Android deployment option creates a separate sub-project for android and makes the main project and associated libraries available to the sub-project as libraries. The sub-project can be edited using NBAndroid (see below) or using Eclipse or any other IDE that supports standard android projects. Normally you do not need to edit the android project files. Exceptions are described further below.
</p>
<p>
Activating the nbandroid plugin in the jMonkeyPlatform is optional, but recommended. You do not need the nbandroid plugin for Android support to work, however nbandroid will not interfere and will in fact allow you to edit the android source files and project more conveniently. To be able to edit, extend and code android-specific code in Android projects, install NBAndroid from the update center:
</p>
<ol>
<li><div> Open Tools→Plugins→Settings</div>
</li>
<li><div> Go to Tools→Plugins→Available Plugins.</div>
</li>
<li><div> Install the NbAndroid plugin. (Will show up as Android)</div>
</li>
</ol>
<p>
Restart the jMonkeyPlatform.
</p>
</div>
<h4><a>Build and Run</a></h4>
<div>
<p>
Open your game project in the jMonkeyPlatform.
</p>
<ol>
<li><div> Right-click the project node and choose Set Main Project.</div>
</li>
<li><div> Right-click the project node to build your project. <br/>
An APK file is created in the &quot;dist&quot; folder.</div>
</li>
<li><div> (Right-click and run the project. The default run target uses the default device set in the Android configuration utility. If you set that to a phone you can run the application directly on your phone!)</div>
</li>
<li><div> Alternatively, select the &quot;Android Device&quot; build configuration next to the Run toolbar button. You can run the project on the emulator (in theory – the emulator doesn’t support OpenGL 2.0 yet?)</div>
</li>
</ol>
<p>
Optionally, download <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/downloads/detail?name=Jme3Beta1Demo.apk&amp;can=1&amp;q="><param name="text" value="<html><u>Jme3Beta1Demo.apk</u></html>"><param name="textColor" value="blue"></object>
</p>
</div>
<h4><a>Beta Notes</a></h4>
<div>
<ul>
<li><div> The package name parameter is only used when creating the project and only sets the android MainActivity package name</div>
</li>
<li><div> The needed jMonkeyEngine3.jar for android comes with the plugin and is automatically added to the android build</div>
</li>
<li><div> All non-android project libraries are automatically excluded from the android build. This is currently hard-coded in the build script, check nbproject/mobile-impl.xml for the details.</div>
</li>
<li><div> The main application class parameter for the AndroidHarness is taken from the jme3 project settings when enabling android deployment. Currently it is not updated when you change the main class package or name.</div>
</li>
<li><div> When you disable the mobile deployment option, the whole “mobile” folder is deleted.</div>
</li>
<li><div> The &quot;errors&quot; shown in the MainActivity are wrongly displayed only in the editor and will disappear when you install NBAndroid (see below).</div>
</li>
<li><div> To sign your application, edit the mobile/build.properties file to point at valid keystore files.</div>
</li>
</ul>
</div>
<h2><a>Android Considerations</a></h2>
<div>
<p>
You can use the jMonkeyPlatform to save (theoretically) any jMonkeyEngine app as Android app. But the application has to be prepared for the fact that Android devices have a smaller screen resolution, touchscreens instead of mouse buttons, and (typically) no keyboards.
</p>
<ul>
<li><div> <strong>Inputs:</strong> Devise an alternate control scheme that works for Android users (e.g. using com.jme3.input.controls.TouchListener). This mobile scheme is likely quite different from the desktop scheme.</div>
</li>
<li><div> <strong>Effects:</strong> Android devices do no support 3D features as well as PCs – or even not at all. E.g. post-processor filters (depth-of-field blur, bloom, light scattering, cartoon, etc), drop shadows, water effects, 3D Audio. Be prepared that these effects will (at best) slow down the application or (in the worst case) not work at all. Provide the option to switch to a low-fi equivalent! </div>
</li>
<li><div> <strong>Nifty <acronym title="Graphical User Interface">GUI</acronym>:</strong> Use different base UI layout <acronym title="Extensible Markup Language">XML</acronym> files for the mobile version of your app to account for the different screen settings.</div>
</li>
</ul>
<p>
<strong>Best Practice:</strong> Ideally, you write the core application code in a way that it checks for the environment it&#039;s being run on, and automatically adapts the device&#039;s limitations by switching off effects, changing input mechanisms etc. Learn how to <a href="/com/jme3/gde/core/docs/jme3/advanced/read_graphic_card_capabilites.html">read graphic card capabilites</a> here.
</p>
</div>
<h2><a>Using Android specific functions</a></h2>
<div>
<p>
As described above, you should always try to design your application as platform independent as possible. If your game becomes a sudden hit on android, why not release it on Facebook as an applet as well? When your application is designed in a platform independent way, you don&#039;t have to do much more but check a checkbox to deploy your application as an applet. But what if you want to for example access the camera of an android device? Inevitably you will have to use android specific api to access the camera.
</p>
<p>
Since the main project is not configured to access the android api directly, you have to install NBAndroid (see above) to be able to edit the created android project in the <acronym title="Software Development Kit">SDK</acronym>. After installing, click the &quot;open project&quot; button and navigate to the &quot;mobile&quot; folder inside the main project folder (it should show up with an android &quot;a&quot; icon) and open it.
</p>
<p>
<img src="nbdocs:/com/jme3/gde/core/docs/jme3/android_access.png">
Although you will use android specific api, using a camera is not exactly android specific and so you should try to design this part of the application as platform independent as possible as well. As an example, if you want to use the phones camera as an image input stream for a texture, you can create e.g. the AppState that manages the image and makes it available to the application inside the main project (no android code is needed). Then in the android part of the code you make a connection to the camera and update the image in the AppState. This also allows you to easily support cameras on other platforms in the same way or fallback to something else in case the platform doesn&#039;t support a camera.
</p>
</div>
<h2><a>More Info</a></h2>
<div>
<p>
The <acronym title="Software Development Kit">SDK</acronym> will later provide tools to adapt the material and other graphics settings of the Android deployment version automatically.
</p>
<ul>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/android/forum/topic/android-deployment-via-checkbox-is-here"><param name="text" value="<html><u>Android Forum Thread (beta)</u></html>"><param name="textColor" value="blue"></object></div>
</li>
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/groups/android/forum/topic/how-to-run-your-jme3-application-on-android-androidharness"><param name="text" value="<html><u>Android Forum Thread (alpha)</u></html>"><param name="textColor" value="blue"></object></div>
</li>
</ul>
</div>
<p><em><a href="http://direct.jmonkeyengine.org/wiki/doku.php/jme3:android?do=export_xhtmlbody">view online version</a></em></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save