mouse_picking.html 13 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><meta name="keywords" content="documentation, node, ray, click, collision, keyinput, input"><title>Mouse Picking</title><link rel="stylesheet" href="./asciidoctor.css">
  2. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  3. <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"><link rel="stylesheet" href="/home/travis/build/jMonkeyEngine/wiki/build/asciidoc/html5/jme3/advanced/twemoji-awesome.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/mouse_picking.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>Mouse Picking</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#pick-a-target-using-fixed-crosshairs">Pick a Target Using Fixed Crosshairs</a></li><li><a href="#pick-a-target-using-the-mouse-pointer">Pick a Target Using the Mouse Pointer</a></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><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></div>
  4. <div class="paragraph"><p><span class="image"><img src="../../jme3/advanced/mouse-picking.png" alt="mouse-picking.png" width="" height=""></span></p></div>
  5. <div class="paragraph"><p>See <a href="../../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></div></div>
  6. <div class="sect1"><h2 id="pick-a-target-using-fixed-crosshairs">Pick a Target Using Fixed Crosshairs</h2><div class="sectionbody"><div class="paragraph"><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 this method together with a first-person flyCam.</p></div>
  7. <div class="olist arabic"><ol class="arabic"><li><p>Activate the first-person camera: <code>flyCam.setEnabled(true);</code></p></li><li><p>Keep mouse pointer invisible using <code>inputManager.setCursorVisible(false)</code>.</p></li><li><p>Map the <code>pick target</code> action to a MouseButtonTrigger.</p></li><li><p>Implement the action in the Listener.</p></li></ol></div>
  8. <div class="paragraph"><p>The following example rotates Spatials named “Red Box or “Blue Box 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></div>
  9. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="directive">private</span> AnalogListener analogListener = <span class="keyword">new</span> AnalogListener() {
  10. <span class="directive">public</span> <span class="type">void</span> onAnalog(<span class="predefined-type">String</span> name, <span class="type">float</span> intensity, <span class="type">float</span> tpf) {
  11. <span class="keyword">if</span> (name.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">pick target</span><span class="delimiter">&quot;</span></span>)) {
  12. <span class="comment">// Reset results list.</span>
  13. CollisionResults results = <span class="keyword">new</span> CollisionResults();
  14. <span class="comment">// Aim the ray from camera location in camera direction</span>
  15. <span class="comment">// (assuming crosshairs in center of screen).</span>
  16. Ray ray = <span class="keyword">new</span> Ray(cam.getLocation(), cam.getDirection());
  17. <span class="comment">// Collect intersections between ray and all nodes in results list.</span>
  18. rootNode.collideWith(ray, results);
  19. <span class="comment">// Print the results so we see what is going on</span>
  20. <span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i &lt; results.size(); i++) {
  21. <span class="comment">// For each “hit”, we know distance, impact point, geometry.</span>
  22. <span class="type">float</span> dist = results.getCollision(i).getDistance();
  23. Vector3f pt = results.getCollision(i).getContactPoint();
  24. <span class="predefined-type">String</span> target = results.getCollision(i).getGeometry().getName();
  25. <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">Selection #</span><span class="delimiter">&quot;</span></span> + i + <span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span> + target + <span class="string"><span class="delimiter">&quot;</span><span class="content"> at </span><span class="delimiter">&quot;</span></span> + pt + <span class="string"><span class="delimiter">&quot;</span><span class="content">, </span><span class="delimiter">&quot;</span></span> + dist + <span class="string"><span class="delimiter">&quot;</span><span class="content"> WU away.</span><span class="delimiter">&quot;</span></span>);
  26. }
  27. <span class="comment">// 5. Use the results -- we rotate the selected geometry.</span>
  28. <span class="keyword">if</span> (results.size() &gt; <span class="integer">0</span>) {
  29. <span class="comment">// The closest result is the target that the player picked:</span>
  30. Geometry target = results.getClosestCollision().getGeometry();
  31. <span class="comment">// Here comes the action:</span>
  32. <span class="keyword">if</span>(target.getName().equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Red Box</span><span class="delimiter">&quot;</span></span>))
  33. target.rotate(<span class="integer">0</span>, - intensity, <span class="integer">0</span>);
  34. <span class="keyword">else</span> <span class="keyword">if</span>(target.getName().equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Blue Box</span><span class="delimiter">&quot;</span></span>))
  35. target.rotate(<span class="integer">0</span>, intensity, <span class="integer">0</span>);
  36. }
  37. } <span class="comment">// else if ...</span>
  38. }
  39. };</code></pre></div></div></div></div>
  40. <div class="sect1"><h2 id="pick-a-target-using-the-mouse-pointer">Pick a Target Using the Mouse Pointer</h2><div class="sectionbody"><div class="paragraph"><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></div>
  41. <div class="paragraph"><p><strong>Note:</strong> Picking with a visible mouse 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></div>
  42. <div class="olist arabic"><ol class="arabic"><li><p>Map the <code>pick target</code> action to a MouseButtonTrigger.</p></li><li><p>Make the mouse pointer visible using <code>inputManager.setCursorVisible(true)</code>.</p></li><li><p>Remap the inputs for camera rotation, or deactivate camera rotation.</p></li><li><p>Implement the action in the Listener.</p></li></ol></div>
  43. <div class="paragraph"><p>The following example rotates Spatials named “Red Box or “Blue Box 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></div>
  44. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> AnalogListener analogListener = <span class="keyword">new</span> AnalogListener() {
  45. <span class="directive">public</span> <span class="type">void</span> onAnalog(<span class="predefined-type">String</span> name, <span class="type">float</span> intensity, <span class="type">float</span> tpf) {
  46. <span class="keyword">if</span> (name.equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">pick target</span><span class="delimiter">&quot;</span></span>)) {
  47. <span class="comment">// Reset results list.</span>
  48. CollisionResults results = <span class="keyword">new</span> CollisionResults();
  49. <span class="comment">// Convert screen click to 3d position</span>
  50. Vector2f click2d = inputManager.getCursorPosition();
  51. Vector3f click3d = cam.getWorldCoordinates(<span class="keyword">new</span> Vector2f(click2d.x, click2d.y), <span class="float">0f</span>).clone();
  52. Vector3f dir = cam.getWorldCoordinates(<span class="keyword">new</span> Vector2f(click2d.x, click2d.y), <span class="float">1f</span>).subtractLocal(click3d).normalizeLocal();
  53. <span class="comment">// Aim the ray from the clicked spot forwards.</span>
  54. Ray ray = <span class="keyword">new</span> Ray(click3d, dir);
  55. <span class="comment">// Collect intersections between ray and all nodes in results list.</span>
  56. rootNode.collideWith(ray, results);
  57. <span class="comment">// (Print the results so we see what is going on:)</span>
  58. <span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i &lt; results.size(); i++) {
  59. <span class="comment">// (For each “hit”, we know distance, impact point, geometry.)</span>
  60. <span class="type">float</span> dist = results.getCollision(i).getDistance();
  61. Vector3f pt = results.getCollision(i).getContactPoint();
  62. <span class="predefined-type">String</span> target = results.getCollision(i).getGeometry().getName();
  63. <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">Selection #</span><span class="delimiter">&quot;</span></span> + i + <span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span> + target + <span class="string"><span class="delimiter">&quot;</span><span class="content"> at </span><span class="delimiter">&quot;</span></span> + pt + <span class="string"><span class="delimiter">&quot;</span><span class="content">, </span><span class="delimiter">&quot;</span></span> + dist + <span class="string"><span class="delimiter">&quot;</span><span class="content"> WU away.</span><span class="delimiter">&quot;</span></span>);
  64. }
  65. <span class="comment">// Use the results -- we rotate the selected geometry.</span>
  66. <span class="keyword">if</span> (results.size() &gt; <span class="integer">0</span>) {
  67. <span class="comment">// The closest result is the target that the player picked:</span>
  68. Geometry target = results.getClosestCollision().getGeometry();
  69. <span class="comment">// Here comes the action:</span>
  70. <span class="keyword">if</span> (target.getName().equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Red Box</span><span class="delimiter">&quot;</span></span>)) {
  71. target.rotate(<span class="integer">0</span>, -intensity, <span class="integer">0</span>);
  72. } <span class="keyword">else</span> <span class="keyword">if</span> (target.getName().equals(<span class="string"><span class="delimiter">&quot;</span><span class="content">Blue Box</span><span class="delimiter">&quot;</span></span>)) {
  73. target.rotate(<span class="integer">0</span>, intensity, <span class="integer">0</span>);
  74. }
  75. }
  76. } <span class="comment">// else if ...</span>
  77. }
  78. };</code></pre></div></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-20 23:30:51 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
  79. apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
  80. indexName: 'jmonkeyengine',
  81. inputSelector: '#doc-search',
  82. debug: false // Set debug to true if you want to inspect the dropdown
  83. });</script></body></html>