hello_picking.html 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <meta name="generator" content="Asciidoctor 1.5.4">
  8. <title>jMonkeyEngine 3 Tutorial (8) - Hello Picking</title>
  9. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
  10. <style>
  11. /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
  12. /* Remove comment around @import statement below when using as a custom stylesheet */
  13. /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
  14. article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
  15. audio,canvas,video{display:inline-block}
  16. audio:not([controls]){display:none;height:0}
  17. [hidden],template{display:none}
  18. script{display:none!important}
  19. html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
  20. body{margin:0}
  21. a{background:transparent}
  22. a:focus{outline:thin dotted}
  23. a:active,a:hover{outline:0}
  24. h1{font-size:2em;margin:.67em 0}
  25. abbr[title]{border-bottom:1px dotted}
  26. b,strong{font-weight:bold}
  27. dfn{font-style:italic}
  28. hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
  29. mark{background:#ff0;color:#000}
  30. code,kbd,pre,samp{font-family:monospace;font-size:1em}
  31. pre{white-space:pre-wrap}
  32. q{quotes:"\201C" "\201D" "\2018" "\2019"}
  33. small{font-size:80%}
  34. sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
  35. sup{top:-.5em}
  36. sub{bottom:-.25em}
  37. img{border:0}
  38. svg:not(:root){overflow:hidden}
  39. figure{margin:0}
  40. fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
  41. legend{border:0;padding:0}
  42. button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
  43. button,input{line-height:normal}
  44. button,select{text-transform:none}
  45. button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
  46. button[disabled],html input[disabled]{cursor:default}
  47. input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
  48. input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
  49. input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
  50. button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
  51. textarea{overflow:auto;vertical-align:top}
  52. table{border-collapse:collapse;border-spacing:0}
  53. *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
  54. html,body{font-size:100%}
  55. body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
  56. a:hover{cursor:pointer}
  57. img,object,embed{max-width:100%;height:auto}
  58. object,embed{height:100%}
  59. img{-ms-interpolation-mode:bicubic}
  60. .left{float:left!important}
  61. .right{float:right!important}
  62. .text-left{text-align:left!important}
  63. .text-right{text-align:right!important}
  64. .text-center{text-align:center!important}
  65. .text-justify{text-align:justify!important}
  66. .hide{display:none}
  67. body{-webkit-font-smoothing:antialiased}
  68. img,object,svg{display:inline-block;vertical-align:middle}
  69. textarea{height:auto;min-height:50px}
  70. select{width:100%}
  71. .center{margin-left:auto;margin-right:auto}
  72. .spread{width:100%}
  73. p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
  74. .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
  75. div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
  76. a{color:#2156a5;text-decoration:underline;line-height:inherit}
  77. a:hover,a:focus{color:#1d4b8f}
  78. a img{border:none}
  79. p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
  80. p aside{font-size:.875em;line-height:1.35;font-style:italic}
  81. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
  82. h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
  83. h1{font-size:2.125em}
  84. h2{font-size:1.6875em}
  85. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
  86. h4,h5{font-size:1.125em}
  87. h6{font-size:1em}
  88. hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
  89. em,i{font-style:italic;line-height:inherit}
  90. strong,b{font-weight:bold;line-height:inherit}
  91. small{font-size:60%;line-height:inherit}
  92. code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
  93. ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
  94. ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
  95. ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
  96. ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
  97. ul.square{list-style-type:square}
  98. ul.circle{list-style-type:circle}
  99. ul.disc{list-style-type:disc}
  100. ul.no-bullet{list-style:none}
  101. ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
  102. dl dt{margin-bottom:.3125em;font-weight:bold}
  103. dl dd{margin-bottom:1.25em}
  104. abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
  105. abbr{text-transform:none}
  106. blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
  107. blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
  108. blockquote cite:before{content:"\2014 \0020"}
  109. blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
  110. blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
  111. @media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
  112. h1{font-size:2.75em}
  113. h2{font-size:2.3125em}
  114. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
  115. h4{font-size:1.4375em}}
  116. table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
  117. table thead,table tfoot{background:#f7f8f7;font-weight:bold}
  118. table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
  119. table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
  120. table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
  121. table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
  122. body{tab-size:4}
  123. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
  124. h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
  125. .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
  126. .clearfix:after,.float-group:after{clear:both}
  127. *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
  128. pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
  129. .keyseq{color:rgba(51,51,51,.8)}
  130. kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
  131. .keyseq kbd:first-child{margin-left:0}
  132. .keyseq kbd:last-child{margin-right:0}
  133. .menuseq,.menu{color:rgba(0,0,0,.8)}
  134. b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
  135. b.button:before{content:"[";padding:0 3px 0 2px}
  136. b.button:after{content:"]";padding:0 2px 0 3px}
  137. p a>code:hover{color:rgba(0,0,0,.9)}
  138. #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
  139. #header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
  140. #header:after,#content:after,#footnotes:after,#footer:after{clear:both}
  141. #content{margin-top:1.25em}
  142. #content:before{content:none}
  143. #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
  144. #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
  145. #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
  146. #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
  147. #header .details span:first-child{margin-left:-.125em}
  148. #header .details span.email a{color:rgba(0,0,0,.85)}
  149. #header .details br{display:none}
  150. #header .details br+span:before{content:"\00a0\2013\00a0"}
  151. #header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
  152. #header .details br+span#revremark:before{content:"\00a0|\00a0"}
  153. #header #revnumber{text-transform:capitalize}
  154. #header #revnumber:after{content:"\00a0"}
  155. #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
  156. #toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
  157. #toc>ul{margin-left:.125em}
  158. #toc ul.sectlevel0>li>a{font-style:italic}
  159. #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
  160. #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
  161. #toc li{line-height:1.3334;margin-top:.3334em}
  162. #toc a{text-decoration:none}
  163. #toc a:active{text-decoration:underline}
  164. #toctitle{color:#7a2518;font-size:1.2em}
  165. @media only screen and (min-width:768px){#toctitle{font-size:1.375em}
  166. body.toc2{padding-left:15em;padding-right:0}
  167. #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
  168. #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
  169. #toc.toc2>ul{font-size:.9em;margin-bottom:0}
  170. #toc.toc2 ul ul{margin-left:0;padding-left:1em}
  171. #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
  172. body.toc2.toc-right{padding-left:0;padding-right:15em}
  173. body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
  174. @media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
  175. #toc.toc2{width:20em}
  176. #toc.toc2 #toctitle{font-size:1.375em}
  177. #toc.toc2>ul{font-size:.95em}
  178. #toc.toc2 ul ul{padding-left:1.25em}
  179. body.toc2.toc-right{padding-left:0;padding-right:20em}}
  180. #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  181. #content #toc>:first-child{margin-top:0}
  182. #content #toc>:last-child{margin-bottom:0}
  183. #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
  184. #footer-text{color:rgba(255,255,255,.8);line-height:1.44}
  185. .sect1{padding-bottom:.625em}
  186. @media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
  187. .sect1+.sect1{border-top:1px solid #efefed}
  188. #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
  189. #content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
  190. #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
  191. #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
  192. #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
  193. .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
  194. .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
  195. table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
  196. .paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
  197. table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
  198. .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
  199. .admonitionblock>table td.icon{text-align:center;width:80px}
  200. .admonitionblock>table td.icon img{max-width:none}
  201. .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
  202. .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
  203. .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
  204. .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
  205. .exampleblock>.content>:first-child{margin-top:0}
  206. .exampleblock>.content>:last-child{margin-bottom:0}
  207. .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  208. .sidebarblock>:first-child{margin-top:0}
  209. .sidebarblock>:last-child{margin-bottom:0}
  210. .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
  211. .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
  212. .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
  213. .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
  214. .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
  215. .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
  216. @media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
  217. @media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
  218. .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
  219. .listingblock pre.highlightjs{padding:0}
  220. .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
  221. .listingblock pre.prettyprint{border-width:0}
  222. .listingblock>.content{position:relative}
  223. .listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
  224. .listingblock:hover code[data-lang]:before{display:block}
  225. .listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
  226. .listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
  227. table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
  228. table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
  229. table.pyhltable td.code{padding-left:.75em;padding-right:0}
  230. pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
  231. pre.pygments .lineno{display:inline-block;margin-right:.25em}
  232. table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
  233. .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
  234. .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
  235. .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
  236. .quoteblock blockquote{margin:0;padding:0;border:0}
  237. .quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
  238. .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
  239. .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
  240. .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
  241. .quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
  242. .quoteblock .quoteblock blockquote:before{display:none}
  243. .verseblock{margin:0 1em 1.25em 1em}
  244. .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
  245. .verseblock pre strong{font-weight:400}
  246. .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
  247. .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
  248. .quoteblock .attribution br,.verseblock .attribution br{display:none}
  249. .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
  250. .quoteblock.abstract{margin:0 0 1.25em 0;display:block}
  251. .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
  252. .quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
  253. table.tableblock{max-width:100%;border-collapse:separate}
  254. table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
  255. table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
  256. table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
  257. table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
  258. table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
  259. table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
  260. table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
  261. table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
  262. table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
  263. table.frame-all{border-width:1px}
  264. table.frame-sides{border-width:0 1px}
  265. table.frame-topbot{border-width:1px 0}
  266. th.halign-left,td.halign-left{text-align:left}
  267. th.halign-right,td.halign-right{text-align:right}
  268. th.halign-center,td.halign-center{text-align:center}
  269. th.valign-top,td.valign-top{vertical-align:top}
  270. th.valign-bottom,td.valign-bottom{vertical-align:bottom}
  271. th.valign-middle,td.valign-middle{vertical-align:middle}
  272. table thead th,table tfoot th{font-weight:bold}
  273. tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
  274. tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
  275. p.tableblock>code:only-child{background:none;padding:0}
  276. p.tableblock{font-size:1em}
  277. td>div.verse{white-space:pre}
  278. ol{margin-left:1.75em}
  279. ul li ol{margin-left:1.5em}
  280. dl dd{margin-left:1.125em}
  281. dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
  282. ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
  283. ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
  284. ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
  285. ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
  286. ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
  287. ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
  288. ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
  289. ul.inline>li>*{display:block}
  290. .unstyled dl dt{font-weight:400;font-style:normal}
  291. ol.arabic{list-style-type:decimal}
  292. ol.decimal{list-style-type:decimal-leading-zero}
  293. ol.loweralpha{list-style-type:lower-alpha}
  294. ol.upperalpha{list-style-type:upper-alpha}
  295. ol.lowerroman{list-style-type:lower-roman}
  296. ol.upperroman{list-style-type:upper-roman}
  297. ol.lowergreek{list-style-type:lower-greek}
  298. .hdlist>table,.colist>table{border:0;background:none}
  299. .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
  300. td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
  301. td.hdlist1{font-weight:bold;padding-bottom:1.25em}
  302. .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
  303. .colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
  304. .colist>table tr>td:last-of-type{padding:.25em 0}
  305. .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
  306. .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
  307. .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
  308. .imageblock>.title{margin-bottom:0}
  309. .imageblock.thumb,.imageblock.th{border-width:6px}
  310. .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
  311. .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
  312. .image.left{margin-right:.625em}
  313. .image.right{margin-left:.625em}
  314. a.image{text-decoration:none;display:inline-block}
  315. a.image object{pointer-events:none}
  316. sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
  317. sup.footnote a,sup.footnoteref a{text-decoration:none}
  318. sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
  319. #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
  320. #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
  321. #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
  322. #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
  323. #footnotes .footnote:last-of-type{margin-bottom:0}
  324. #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
  325. .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
  326. .gist .file-data>table td.line-data{width:99%}
  327. div.unbreakable{page-break-inside:avoid}
  328. .big{font-size:larger}
  329. .small{font-size:smaller}
  330. .underline{text-decoration:underline}
  331. .overline{text-decoration:overline}
  332. .line-through{text-decoration:line-through}
  333. .aqua{color:#00bfbf}
  334. .aqua-background{background-color:#00fafa}
  335. .black{color:#000}
  336. .black-background{background-color:#000}
  337. .blue{color:#0000bf}
  338. .blue-background{background-color:#0000fa}
  339. .fuchsia{color:#bf00bf}
  340. .fuchsia-background{background-color:#fa00fa}
  341. .gray{color:#606060}
  342. .gray-background{background-color:#7d7d7d}
  343. .green{color:#006000}
  344. .green-background{background-color:#007d00}
  345. .lime{color:#00bf00}
  346. .lime-background{background-color:#00fa00}
  347. .maroon{color:#600000}
  348. .maroon-background{background-color:#7d0000}
  349. .navy{color:#000060}
  350. .navy-background{background-color:#00007d}
  351. .olive{color:#606000}
  352. .olive-background{background-color:#7d7d00}
  353. .purple{color:#600060}
  354. .purple-background{background-color:#7d007d}
  355. .red{color:#bf0000}
  356. .red-background{background-color:#fa0000}
  357. .silver{color:#909090}
  358. .silver-background{background-color:#bcbcbc}
  359. .teal{color:#006060}
  360. .teal-background{background-color:#007d7d}
  361. .white{color:#bfbfbf}
  362. .white-background{background-color:#fafafa}
  363. .yellow{color:#bfbf00}
  364. .yellow-background{background-color:#fafa00}
  365. span.icon>.fa{cursor:default}
  366. .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
  367. .admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
  368. .admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
  369. .admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
  370. .admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
  371. .admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
  372. .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
  373. .conum[data-value] *{color:#fff!important}
  374. .conum[data-value]+b{display:none}
  375. .conum[data-value]:after{content:attr(data-value)}
  376. pre .conum[data-value]{position:relative;top:-.125em}
  377. b.conum *{color:inherit!important}
  378. .conum:not([data-value]):empty{display:none}
  379. dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
  380. h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
  381. p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
  382. p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
  383. p{margin-bottom:1.25rem}
  384. .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
  385. .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
  386. .print-only{display:none!important}
  387. @media print{@page{margin:1.25cm .75cm}
  388. *{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
  389. a{color:inherit!important;text-decoration:underline!important}
  390. a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
  391. a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
  392. abbr[title]:after{content:" (" attr(title) ")"}
  393. pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
  394. thead{display:table-header-group}
  395. svg{max-width:100%}
  396. p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
  397. h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
  398. #toc,.sidebarblock,.exampleblock>.content{background:none!important}
  399. #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
  400. .sect1{padding-bottom:0!important}
  401. .sect1+.sect1{border:0!important}
  402. #header>h1:first-child{margin-top:1.25rem}
  403. body.book #header{text-align:center}
  404. body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
  405. body.book #header .details{border:0!important;display:block;padding:0!important}
  406. body.book #header .details span:first-child{margin-left:0!important}
  407. body.book #header .details br{display:block}
  408. body.book #header .details br+span:before{content:none!important}
  409. body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
  410. body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
  411. .listingblock code[data-lang]:before{display:block}
  412. #footer{background:none!important;padding:0 .9375em}
  413. #footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
  414. .hide-on-print{display:none!important}
  415. .print-only{display:block!important}
  416. .hide-for-print{display:none!important}
  417. .show-for-print{display:inherit!important}}
  418. </style>
  419. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  420. <style>
  421. /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
  422. /*pre.CodeRay {background-color:#f7f7f8;}*/
  423. .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
  424. .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
  425. .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
  426. table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
  427. table.CodeRay td{vertical-align: top;line-height:1.45}
  428. table.CodeRay td.line-numbers{text-align:right}
  429. table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
  430. table.CodeRay td.code{padding:0 0 0 .5em}
  431. table.CodeRay td.code>pre{padding:0}
  432. .CodeRay .debug{color:#fff !important;background:#000080 !important}
  433. .CodeRay .annotation{color:#007}
  434. .CodeRay .attribute-name{color:#000080}
  435. .CodeRay .attribute-value{color:#700}
  436. .CodeRay .binary{color:#509}
  437. .CodeRay .comment{color:#998;font-style:italic}
  438. .CodeRay .char{color:#04d}
  439. .CodeRay .char .content{color:#04d}
  440. .CodeRay .char .delimiter{color:#039}
  441. .CodeRay .class{color:#458;font-weight:bold}
  442. .CodeRay .complex{color:#a08}
  443. .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
  444. .CodeRay .color{color:#099}
  445. .CodeRay .class-variable{color:#369}
  446. .CodeRay .decorator{color:#b0b}
  447. .CodeRay .definition{color:#099}
  448. .CodeRay .delimiter{color:#000}
  449. .CodeRay .doc{color:#970}
  450. .CodeRay .doctype{color:#34b}
  451. .CodeRay .doc-string{color:#d42}
  452. .CodeRay .escape{color:#666}
  453. .CodeRay .entity{color:#800}
  454. .CodeRay .error{color:#808}
  455. .CodeRay .exception{color:inherit}
  456. .CodeRay .filename{color:#099}
  457. .CodeRay .function{color:#900;font-weight:bold}
  458. .CodeRay .global-variable{color:#008080}
  459. .CodeRay .hex{color:#058}
  460. .CodeRay .integer,.CodeRay .float{color:#099}
  461. .CodeRay .include{color:#555}
  462. .CodeRay .inline{color:#000}
  463. .CodeRay .inline .inline{background:#ccc}
  464. .CodeRay .inline .inline .inline{background:#bbb}
  465. .CodeRay .inline .inline-delimiter{color:#d14}
  466. .CodeRay .inline-delimiter{color:#d14}
  467. .CodeRay .important{color:#555;font-weight:bold}
  468. .CodeRay .interpreted{color:#b2b}
  469. .CodeRay .instance-variable{color:#008080}
  470. .CodeRay .label{color:#970}
  471. .CodeRay .local-variable{color:#963}
  472. .CodeRay .octal{color:#40e}
  473. .CodeRay .predefined{color:#369}
  474. .CodeRay .preprocessor{color:#579}
  475. .CodeRay .pseudo-class{color:#555}
  476. .CodeRay .directive{font-weight:bold}
  477. .CodeRay .type{font-weight:bold}
  478. .CodeRay .predefined-type{color:inherit}
  479. .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
  480. .CodeRay .key{color:#808}
  481. .CodeRay .key .delimiter{color:#606}
  482. .CodeRay .key .char{color:#80f}
  483. .CodeRay .value{color:#088}
  484. .CodeRay .regexp .delimiter{color:#808}
  485. .CodeRay .regexp .content{color:#808}
  486. .CodeRay .regexp .modifier{color:#808}
  487. .CodeRay .regexp .char{color:#d14}
  488. .CodeRay .regexp .function{color:#404;font-weight:bold}
  489. .CodeRay .string{color:#d20}
  490. .CodeRay .string .string .string{background:#ffd0d0}
  491. .CodeRay .string .content{color:#d14}
  492. .CodeRay .string .char{color:#d14}
  493. .CodeRay .string .delimiter{color:#d14}
  494. .CodeRay .shell{color:#d14}
  495. .CodeRay .shell .delimiter{color:#d14}
  496. .CodeRay .symbol{color:#990073}
  497. .CodeRay .symbol .content{color:#a60}
  498. .CodeRay .symbol .delimiter{color:#630}
  499. .CodeRay .tag{color:#008080}
  500. .CodeRay .tag-special{color:#d70}
  501. .CodeRay .variable{color:#036}
  502. .CodeRay .insert{background:#afa}
  503. .CodeRay .delete{background:#faa}
  504. .CodeRay .change{color:#aaf;background:#007}
  505. .CodeRay .head{color:#f8f;background:#505}
  506. .CodeRay .insert .insert{color:#080}
  507. .CodeRay .delete .delete{color:#800}
  508. .CodeRay .change .change{color:#66f}
  509. .CodeRay .head .head{color:#f4f}
  510. </style>
  511. </head>
  512. <body class="article toc2 toc-left">
  513. <div id="header">
  514. <h1>jMonkeyEngine 3 Tutorial (8) - Hello Picking</h1>
  515. <div id="toc" class="toc2">
  516. <div id="toctitle">Table of Contents</div>
  517. <ul class="sectlevel1">
  518. <li><a href="#sample-code">Sample Code</a></li>
  519. <li><a href="#understanding-the-helper-methods">Understanding the Helper Methods</a></li>
  520. <li><a href="#understanding-ray-casting-for-hit-testing">Understanding Ray Casting for Hit Testing</a></li>
  521. <li><a href="#implementing-hit-testing">Implementing Hit Testing</a>
  522. <ul class="sectlevel2">
  523. <li><a href="#loading-the-scene">Loading the scene</a></li>
  524. </ul>
  525. </li>
  526. </ul>
  527. </div>
  528. </div>
  529. <div id="content">
  530. <div id="preamble">
  531. <div class="sectionbody">
  532. <div class="paragraph">
  533. <p>Previous: <a href="hello_animation.html">Hello Animation</a>,
  534. Next: <a href="hello_collision.html">Hello Collision</a></p>
  535. </div>
  536. <div class="paragraph">
  537. <p>Typical interactions in games include shooting, picking up objects, and opening doors. From an implementation point of view, these apparently different interactions are surprisingly similar: The user first aims and selects a target in the 3D scene, and then triggers an action on it. We call this process picking.</p>
  538. </div>
  539. <div class="paragraph">
  540. <p>You can pick something by either pressing a key on the keyboard, or by clicking with the mouse. In either case, you identify the target by aiming a ray –a straight line– into the scene. This method to implement picking is called <em>ray casting</em> (which is not the same as <em>ray tracing</em>).</p>
  541. </div>
  542. <div class="paragraph">
  543. <p>This tutorial relies on what you have learned in the <a href="jme3/beginner/hello_input_system.html">Hello Input</a> tutorial. You find more related code samples under <a href="jme3/advanced/mouse_picking.html">Mouse Picking</a> and <a href="jme3/advanced/collision_and_intersection.html">Collision and Intersection</a>.</p>
  544. </div>
  545. <div class="imageblock" style="text-align: center">
  546. <div class="content">
  547. <img src="images/beginner-picking.png" alt="beginner-picking.png" height="">
  548. </div>
  549. </div>
  550. </div>
  551. </div>
  552. <div class="sect1">
  553. <h2 id="sample-code">Sample Code</h2>
  554. <div class="sectionbody">
  555. <div class="listingblock">
  556. <div class="content">
  557. <pre class="CodeRay highlight"><code data-lang="java">----<span class="keyword">package</span> <span class="namespace">jme3test.helloworld</span>;</code></pre>
  558. </div>
  559. </div>
  560. <div class="paragraph">
  561. <p>import com.jme3.app.SimpleApplication;
  562. import com.jme3.collision.CollisionResult;
  563. import com.jme3.collision.CollisionResults;
  564. import com.jme3.font.BitmapText;
  565. import com.jme3.input.KeyInput;
  566. import com.jme3.input.MouseInput;
  567. import com.jme3.input.controls.ActionListener;
  568. import com.jme3.input.controls.KeyTrigger;
  569. import com.jme3.input.controls.MouseButtonTrigger;
  570. import com.jme3.light.DirectionalLight;
  571. import com.jme3.material.Material;
  572. import com.jme3.math.ColorRGBA;
  573. import com.jme3.math.Ray;
  574. import com.jme3.math.Vector3f;
  575. import com.jme3.scene.Geometry;
  576. import com.jme3.scene.Node;
  577. import com.jme3.scene.Spatial;
  578. import com.jme3.scene.shape.Box;
  579. import com.jme3.scene.shape.Sphere;</p>
  580. </div>
  581. <div class="paragraph">
  582. <p>/** Sample 8 - how to let the user pick (select) objects in the scene
  583. * using the mouse or key presses. Can be used for shooting, opening doors, etc. */
  584. public class HelloPicking extends SimpleApplication {</p>
  585. </div>
  586. <div class="literalblock">
  587. <div class="content">
  588. <pre>public static void main(String[] args) {
  589. HelloPicking app = new HelloPicking();
  590. app.start();
  591. }
  592. private Node shootables;
  593. private Geometry mark;</pre>
  594. </div>
  595. </div>
  596. <div class="literalblock">
  597. <div class="content">
  598. <pre>@Override
  599. public void simpleInitApp() {
  600. initCrossHairs(); // a "+" in the middle of the screen to help aiming
  601. initKeys(); // load custom key mappings
  602. initMark(); // a red sphere to mark the hit</pre>
  603. </div>
  604. </div>
  605. <div class="literalblock">
  606. <div class="content">
  607. <pre> /** create four colored boxes and a floor to shoot at: */
  608. shootables = new Node("Shootables");
  609. rootNode.attachChild(shootables);
  610. shootables.attachChild(makeCube("a Dragon", -2f, 0f, 1f));
  611. shootables.attachChild(makeCube("a tin can", 1f, -2f, 0f));
  612. shootables.attachChild(makeCube("the Sheriff", 0f, 1f, -2f));
  613. shootables.attachChild(makeCube("the Deputy", 1f, 0f, -4f));
  614. shootables.attachChild(makeFloor());
  615. shootables.attachChild(makeCharacter());
  616. }</pre>
  617. </div>
  618. </div>
  619. <div class="literalblock">
  620. <div class="content">
  621. <pre>/** Declaring the "Shoot" action and mapping to its triggers. */
  622. private void initKeys() {
  623. inputManager.addMapping("Shoot",
  624. new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar
  625. new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click
  626. inputManager.addListener(actionListener, "Shoot");
  627. }
  628. /** Defining the "Shoot" action: Determine what was hit and how to respond. */
  629. private ActionListener actionListener = new ActionListener() {</pre>
  630. </div>
  631. </div>
  632. <div class="literalblock">
  633. <div class="content">
  634. <pre> public void onAction(String name, boolean keyPressed, float tpf) {
  635. if (name.equals("Shoot") &amp;&amp; !keyPressed) {
  636. // 1. Reset results list.
  637. CollisionResults results = new CollisionResults();
  638. // 2. Aim the ray from cam loc to cam direction.
  639. Ray ray = new Ray(cam.getLocation(), cam.getDirection());
  640. // 3. Collect intersections between Ray and Shootables in results list.
  641. shootables.collideWith(ray, results);
  642. // 4. Print the results
  643. System.out.println("----- Collisions? " + results.size() + "-----");
  644. for (int i = 0; i &lt; results.size(); i++) {
  645. // For each hit, we know distance, impact point, name of geometry.
  646. float dist = results.getCollision(i).getDistance();
  647. Vector3f pt = results.getCollision(i).getContactPoint();
  648. String hit = results.getCollision(i).getGeometry().getName();
  649. System.out.println("* Collision #" + i);
  650. System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
  651. }
  652. // 5. Use the results (we mark the hit object)
  653. if (results.size() &gt; 0) {
  654. // The closest collision point is what was truly hit:
  655. CollisionResult closest = results.getClosestCollision();
  656. // Let's interact - we mark the hit with a red dot.
  657. mark.setLocalTranslation(closest.getContactPoint());
  658. rootNode.attachChild(mark);
  659. } else {
  660. // No hits? Then remove the red mark.
  661. rootNode.detachChild(mark);
  662. }
  663. }
  664. }
  665. };</pre>
  666. </div>
  667. </div>
  668. <div class="literalblock">
  669. <div class="content">
  670. <pre>/** A cube object for target practice */
  671. protected Geometry makeCube(String name, float x, float y, float z) {
  672. Box box = new Box(1, 1, 1);
  673. Geometry cube = new Geometry(name, box);
  674. cube.setLocalTranslation(x, y, z);
  675. Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
  676. mat1.setColor("Color", ColorRGBA.randomColor());
  677. cube.setMaterial(mat1);
  678. return cube;
  679. }</pre>
  680. </div>
  681. </div>
  682. <div class="literalblock">
  683. <div class="content">
  684. <pre>/** A floor to show that the "shot" can go through several objects. */
  685. protected Geometry makeFloor() {
  686. Box box = new Box(15, .2f, 15);
  687. Geometry floor = new Geometry("the Floor", box);
  688. floor.setLocalTranslation(0, -4, -5);
  689. Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
  690. mat1.setColor("Color", ColorRGBA.Gray);
  691. floor.setMaterial(mat1);
  692. return floor;
  693. }</pre>
  694. </div>
  695. </div>
  696. <div class="literalblock">
  697. <div class="content">
  698. <pre>/** A red ball that marks the last spot that was "hit" by the "shot". */
  699. protected void initMark() {
  700. Sphere sphere = new Sphere(30, 30, 0.2f);
  701. mark = new Geometry("BOOM!", sphere);
  702. Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
  703. mark_mat.setColor("Color", ColorRGBA.Red);
  704. mark.setMaterial(mark_mat);
  705. }</pre>
  706. </div>
  707. </div>
  708. <div class="literalblock">
  709. <div class="content">
  710. <pre>/** A centred plus sign to help the player aim. */
  711. protected void initCrossHairs() {
  712. setDisplayStatView(false);
  713. guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
  714. BitmapText ch = new BitmapText(guiFont, false);
  715. ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
  716. ch.setText("+"); // crosshairs
  717. ch.setLocalTranslation( // center
  718. settings.getWidth() / 2 - ch.getLineWidth()/2, settings.getHeight() / 2 + ch.getLineHeight()/2, 0);
  719. guiNode.attachChild(ch);
  720. }</pre>
  721. </div>
  722. </div>
  723. <div class="literalblock">
  724. <div class="content">
  725. <pre>protected Spatial makeCharacter() {
  726. // load a character from jme3test-test-data
  727. Spatial golem = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
  728. golem.scale(0.5f);
  729. golem.setLocalTranslation(-1.0f, -1.5f, -0.6f);</pre>
  730. </div>
  731. </div>
  732. <div class="literalblock">
  733. <div class="content">
  734. <pre> // We must add a light to make the model visible
  735. DirectionalLight sun = new DirectionalLight();
  736. sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
  737. golem.addLight(sun);
  738. return golem;
  739. }
  740. }----
  741. You should see four colored cubes floating over a gray floor, and cross-hairs. Aim the cross-hairs and click, or press the spacebar to shoot. The hit spot is marked with a red dot.</pre>
  742. </div>
  743. </div>
  744. <div class="paragraph">
  745. <p>Keep an eye on the application&#8217;s output stream, it will give you more details: The name of the mesh that was hit, the coordinates of the hit, and the distance.</p>
  746. </div>
  747. </div>
  748. </div>
  749. <div class="sect1">
  750. <h2 id="understanding-the-helper-methods">Understanding the Helper Methods</h2>
  751. <div class="sectionbody">
  752. <div class="paragraph">
  753. <p>The methods <code>makeCube()</code>, <code>makeFloor()</code>, <code>initMark()</code>, and <code>initCrossHairs</code>, are custom helper methods. We call them from <code>simpleInitApp()</code> to initialize the scenegraph with sample content.</p>
  754. </div>
  755. <div class="olist arabic">
  756. <ol class="arabic">
  757. <li>
  758. <p><code>makeCube()</code> creates simple colored boxes for “target practice.</p>
  759. </li>
  760. <li>
  761. <p><code>makeFloor()</code> creates a gray floor node for “target practice.</p>
  762. </li>
  763. <li>
  764. <p><code>initMark()</code> creates a red sphere (“mark). We will use it later to mark the spot that was hit.</p>
  765. <div class="ulist">
  766. <ul>
  767. <li>
  768. <p>Note that the mark is not attached and therefor not visible at the start!</p>
  769. </li>
  770. </ul>
  771. </div>
  772. </li>
  773. <li>
  774. <p><code>initCrossHairs()</code> creates simple cross-hairs by printing a “+ sign in the middle of the screen.</p>
  775. <div class="ulist">
  776. <ul>
  777. <li>
  778. <p>Note that the cross-hairs are attached to the <code>guiNode</code>, not to the <code>rootNode</code>.</p>
  779. </li>
  780. </ul>
  781. </div>
  782. </li>
  783. </ol>
  784. </div>
  785. <div class="paragraph">
  786. <p>In this example, we attached all “shootable objects to one custom node, <code>Shootables</code>. This is an optimization so the engine only has to calculate intersections with objects we are actually interested in. The <code>Shootables</code> node is attached to the <code>rootNode</code> as usual.</p>
  787. </div>
  788. </div>
  789. </div>
  790. <div class="sect1">
  791. <h2 id="understanding-ray-casting-for-hit-testing">Understanding Ray Casting for Hit Testing</h2>
  792. <div class="sectionbody">
  793. <div class="paragraph">
  794. <p>Our goal is to determine which box the user “shot (picked). In general, we want to determine which mesh the user has selected by aiming the cross-hairs at it. Mathematically, we draw a line from the camera and see whether it intersects with objects in the 3D scene. This line is called a ray.</p>
  795. </div>
  796. <div class="paragraph">
  797. <p>Here is our simple ray casting algorithm for picking objects:</p>
  798. </div>
  799. <div class="olist arabic">
  800. <ol class="arabic">
  801. <li>
  802. <p>Reset the results list.</p>
  803. </li>
  804. <li>
  805. <p>Cast a ray from cam location into the cam direction.</p>
  806. </li>
  807. <li>
  808. <p>Collect all intersections between the ray and <code>Shootable</code> nodes in the <code>results</code> list.</p>
  809. </li>
  810. <li>
  811. <p>Use the results list to determine what was hit:</p>
  812. <div class="olist loweralpha">
  813. <ol class="loweralpha" type="a">
  814. <li>
  815. <p>For each hit, JME reports its distance from the camera, impact point, and the name of the mesh.</p>
  816. </li>
  817. <li>
  818. <p>Sort the results by distance.</p>
  819. </li>
  820. <li>
  821. <p>Take the closest result, it is the mesh that was hit.</p>
  822. </li>
  823. </ol>
  824. </div>
  825. </li>
  826. </ol>
  827. </div>
  828. </div>
  829. </div>
  830. <div class="sect1">
  831. <h2 id="implementing-hit-testing">Implementing Hit Testing</h2>
  832. <div class="sectionbody">
  833. <div class="sect2">
  834. <h3 id="loading-the-scene">Loading the scene</h3>
  835. <div class="paragraph">
  836. <p>First initialize some shootable nodes and attach them to the scene. You will use the <code>mark</code> object later.</p>
  837. </div>
  838. <div class="listingblock">
  839. <div class="content">
  840. <pre class="CodeRay highlight"><code data-lang="java"> Node shootables;
  841. Geometry mark;
  842. <span class="annotation">@Override</span>
  843. <span class="directive">public</span> <span class="type">void</span> simpleInitApp() {
  844. initCrossHairs();
  845. initKeys();
  846. initMark();
  847. shootables = <span class="keyword">new</span> Node(<span class="string"><span class="delimiter">&quot;</span><span class="content">Shootables</span><span class="delimiter">&quot;</span></span>);
  848. rootNode.attachChild(shootables);
  849. shootables.attachChild(makeCube(<span class="string"><span class="delimiter">&quot;</span><span class="content">a Dragon</span><span class="delimiter">&quot;</span></span>, -<span class="float">2f</span>, <span class="float">0f</span>, <span class="float">1f</span>));
  850. shootables.attachChild(makeCube(<span class="string"><span class="delimiter">&quot;</span><span class="content">a tin can</span><span class="delimiter">&quot;</span></span>, <span class="float">1f</span>,-<span class="float">2f</span>, <span class="float">0f</span>));
  851. shootables.attachChild(makeCube(<span class="string"><span class="delimiter">&quot;</span><span class="content">the Sheriff</span><span class="delimiter">&quot;</span></span>, <span class="float">0f</span>, <span class="float">1f</span>,-<span class="float">2f</span>));
  852. shootables.attachChild(makeCube(<span class="string"><span class="delimiter">&quot;</span><span class="content">the Deputy</span><span class="delimiter">&quot;</span></span>, <span class="float">1f</span>, <span class="float">0f</span>, -<span class="integer">4</span>));
  853. shootables.attachChild(makeFloor());
  854. }----
  855. === Setting Up the Input Listener
  856. Next you declare the shooting action. It can be triggered either by clicking, or by pressing the space bar. The <span class="error">`</span>initKeys()<span class="error">`</span> method is called from <span class="error">`</span>simpleInitApp()<span class="error">`</span> to set up these input mappings.
  857. [source,java]</code></pre>
  858. </div>
  859. </div>
  860. <div class="literalblock">
  861. <div class="content">
  862. <pre>/** Declaring the "Shoot" action and its triggers. */
  863. private void initKeys() {
  864. inputManager.addMapping("Shoot", // Declare...
  865. new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar, or
  866. new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click
  867. inputManager.addListener(actionListener, "Shoot"); // ... and add.
  868. }</pre>
  869. </div>
  870. </div>
  871. <div class="listingblock">
  872. <div class="content">
  873. <pre>=== Picking Action Using Crosshairs
  874. Next we implement the ActionListener that responds to the Shoot trigger with an action. The action follows the ray casting algorithm described above:
  875. . For every click or press of the spacebar, the `Shoot` action is triggered.
  876. . The action casts a ray forward and determines intersections with shootable objects (= ray casting).
  877. . For any target that has been hit, it prints name, distance, and coordinates of the hit.
  878. . Finally it attaches a red mark to the closest result, to highlight the spot that was actually hit.
  879. . When nothing was hit, the results list is empty, and the red mark is removed.
  880. Note how it prints a lot of output to show you which hits were registered.
  881. [source,java]
  882. ---- /** Defining the "Shoot" action: Determine what was hit and how to respond. */
  883. private ActionListener actionListener = new ActionListener() {
  884. @Override
  885. public void onAction(String name, boolean keyPressed, float tpf) {
  886. if (name.equals("Shoot") &amp;&amp; !keyPressed) {
  887. // 1. Reset results list.
  888. CollisionResults results = new CollisionResults();
  889. // 2. Aim the ray from cam loc to cam direction.
  890. Ray ray = new Ray(cam.getLocation(), cam.getDirection());
  891. // 3. Collect intersections between Ray and Shootables in results list.
  892. shootables.collideWith(ray, results);
  893. // 4. Print results.
  894. System.out.println("----- Collisions? " + results.size() + "-----");
  895. for (int i = 0; i &lt; results.size(); i++) {
  896. // For each hit, we know distance, impact point, name of geometry.
  897. float dist = results.getCollision(i).getDistance();
  898. Vector3f pt = results.getCollision(i).getContactPoint();
  899. String hit = results.getCollision(i).getGeometry().getName();
  900. System.out.println("* Collision #" + i);
  901. System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
  902. }
  903. // 5. Use the results (we mark the hit object)
  904. if (results.size() &gt; 0){
  905. // The closest collision point is what was truly hit:
  906. CollisionResult closest = results.getClosestCollision();
  907. mark.setLocalTranslation(closest.getContactPoint());
  908. // Let's interact - we mark the hit with a red dot.
  909. rootNode.attachChild(mark);
  910. } else {
  911. // No hits? Then remove the red mark.
  912. rootNode.detachChild(mark);
  913. }
  914. }
  915. }
  916. };----
  917. *Tip:* Notice how you use the provided method `results.getClosestCollision().getContactPoint()` to determine the _closest_ hit's location. If your game includes a “weapon or “spell that can hit multiple targets, you could also loop over the list of results, and interact with each of them.
  918. === Picking Action Using Mouse Pointer
  919. The above example assumes that the player is aiming crosshairs (attached to the center of the screen) at the target. But you can change the picking code to allow you to freely click at objects in the scene with a visible mouse pointer. In order to do this you have to convert the 2d screen coordinates of the click to 3D world coordinates to get the start point of the picking ray.
  920. . Reset result list.
  921. . Get 2D click coordinates.
  922. . Convert 2D screen coordinates to their 3D equivalent.
  923. . Aim the ray from the clicked 3D location forwards into the scene.
  924. . Collect intersections between ray and all nodes into a results list.
  925. [source,java]
  926. ----...
  927. CollisionResults results = new CollisionResults();
  928. Vector2f click2d = inputManager.getCursorPosition();
  929. Vector3f click3d = cam.getWorldCoordinates(
  930. new Vector2f(click2d.x, click2d.y), 0f).clone();
  931. Vector3f dir = cam.getWorldCoordinates(
  932. new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
  933. Ray ray = new Ray(click3d, dir);
  934. shootables.collideWith(ray, results);
  935. ...----
  936. Use this together with `inputManager.setCursorVisible(true)` to make certain the cursor is visible.
  937. Note that since you now use the mouse for picking, you can no longer use it to rotate the camera. If you want to have a visible mouse pointer for picking in your game, you have to redefine the camera rotation mappings.
  938. == Exercises
  939. After a hit was registered, the closest object is identified as target, and marked with a red dot.
  940. Modify the code sample to solve these exercises:
  941. === Exercise 1: Magic Spell
  942. Change the color of the closest clicked target! +
  943. Here are some tips:
  944. . Go to the line where the closest target is indentified, and add your changes after that.
  945. . To change an object's color, you must first know its Geometry. Identify the node by identifying the target's name.
  946. ** Use `Geometry g = closest.getGeometry();`
  947. . Create a new color material and set the node's Material to this color.
  948. ** Look inside the `makeCube()` method for an example of how to set random colors.
  949. === Exercise 2: Shoot a Character
  950. Shooting boxes isn't very exciting – can you add code that loads and positions a model in the scene, and shoot at it?
  951. * Tip: You can use `Spatial golem = assetManager.loadModel(“Models/Oto/Oto.mesh.xml);` from the engine's jme3-test-data.jar.
  952. * Tip: Models are shaded! You need some light!
  953. === Exercise 3: Pick up into Inventory
  954. Change the code as follows to simulate the player picking up objects into the inventory: When you click once, the closest target is identified and detached from the scene. When you click a second time, the target is reattached at the location that you have clicked. Here are some tips:
  955. . Create an inventory node to store the detached nodes temporarily.
  956. . The inventory node is not attached to the rootNode.
  957. . You can make the inventory visible by attaching the inventory node to the guiNode (which attaches it to the HUD). Note the following caveats:
  958. ** If your nodes use a lit Material (not “Unshaded.j3md), also add a light to the guiNode.
  959. ** Size units are pixels in the HUD, therefor a 2-wu cube is displayed only 2 pixels wide in the HUD. – Scale it bigger!
  960. ** Position the nodes: The bottom left corner of the HUD is (0f,0f), and the top right corner is at (settings.getWidth(),settings.getHeight()).
  961. link:http://jmonkeyengine.org/wiki/doku.php/jm3:solutions[http://jmonkeyengine.org/wiki/doku.php/jm3:solutions]
  962. +++&lt;u&gt;Be sure to try to solve them for yourself first!&lt;/u&gt;+++
  963. == Conclusion
  964. You have learned how to use ray casting to solve the task of determining what object a user selected on the screen. You learned that this can be used for a variety of interactions, such as shooting, opening, picking up and dropping items, pressing a button or lever, etc.
  965. Use your imagination from here:
  966. * In your game, the click can trigger any action on the identified Geometry: Detach it and put it into the inventory, attach something to it, trigger an animation or effect, open a door or crate, – etc.
  967. * In your game, you could replace the red mark with a particle emitter, add an explosion effect, play a sound, calculate the new score after each hit depending on what was hit – etc.
  968. Now, wouldn't it be nice if those targets and the floor were solid objects and you could walk around between them? Let's continue to learn about &lt;&lt;hello_collision#,Collision Detection&gt;&gt;.
  969. '''
  970. See also:
  971. * &lt;&lt;jme3/beginner/hello_input_system#,Hello Input&gt;&gt;
  972. * &lt;&lt;jme3/advanced/mouse_picking#,Mouse Picking&gt;&gt;
  973. * &lt;&lt;jme3/advanced/collision_and_intersection#,Collision and Intersection&gt;&gt;
  974. &lt;tags&gt;&lt;tag target="beginner" /&gt;&lt;tag target="documentation" /&gt;&lt;tag target="intro" /&gt;&lt;tag target="node" /&gt;&lt;tag target="ray" /&gt;&lt;tag target="click" /&gt;&lt;tag target="collision" /&gt;&lt;tag target="keyinput" /&gt;&lt;tag target="input" /&gt;&lt;/tags&gt;</pre>
  975. </div>
  976. </div>
  977. </div>
  978. </div>
  979. </div>
  980. </div>
  981. <div id="footer">
  982. <div id="footer-text">
  983. Last updated 2016-05-21 23:44:18 UTC
  984. </div>
  985. </div>
  986. </body>
  987. </html>