hello_terrain.html 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  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 (10) - Hello Terrain</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 (10) - Hello Terrain</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="#what-is-a-heightmap">What is a Heightmap?</a>
  520. <ul class="sectlevel2">
  521. <li><a href="#looking-at-the-heightmap-code">Looking at the Heightmap Code</a></li>
  522. </ul>
  523. </li>
  524. <li><a href="#what-is-texture-splatting">What is Texture Splatting?</a>
  525. <ul class="sectlevel2">
  526. <li><a href="#looking-at-the-texturing-code">Looking at the Texturing Code</a></li>
  527. <li><a href="#exercise-3-solid-terrains">Exercise 3: Solid Terrains</a></li>
  528. </ul>
  529. </li>
  530. <li><a href="#conclusion">Conclusion</a></li>
  531. </ul>
  532. </div>
  533. </div>
  534. <div id="content">
  535. <div id="preamble">
  536. <div class="sectionbody">
  537. <div class="paragraph">
  538. <p>Previous: <a href="hello_collision.html">Hello Collision</a>,
  539. Next: <a href="hello_audio.html">Hello Audio</a></p>
  540. </div>
  541. <div class="paragraph">
  542. <p>One way to create a 3D landscape is to sculpt a huge terrain model. This gives you a lot of artistic freedom – but rendering such a huge model can be quite slow. This tutorial explains how to create fast-rendering terrains from heightmaps, and how to use texture splatting to make the terrain look good.</p>
  543. </div>
  544. <div class="imageblock" style="text-align: center">
  545. <div class="content">
  546. <img src="images/jme3/beginner/beginner-terrain.png" alt="beginner-terrain.png" height="291">
  547. </div>
  548. </div>
  549. <div class="paragraph">
  550. <p>Note: If you get an error when trying to create your ImageBasedHeightMap object, you may need to update the SDK, click on “Help / “Check for updates</p>
  551. </div>
  552. <div class="paragraph">
  553. <p>““““</p>
  554. </div>
  555. </div>
  556. </div>
  557. <div class="sect1">
  558. <h2 id="sample-code">Sample Code</h2>
  559. <div class="sectionbody">
  560. <div class="listingblock">
  561. <div class="content">
  562. <pre class="CodeRay highlight"><code data-lang="java">----<span class="keyword">package</span> <span class="namespace">jme3test.helloworld</span>;</code></pre>
  563. </div>
  564. </div>
  565. <div class="paragraph">
  566. <p>import com.jme3.app.SimpleApplication;
  567. import com.jme3.material.Material;
  568. import com.jme3.renderer.Camera;
  569. import com.jme3.terrain.geomipmap.TerrainLodControl;
  570. import com.jme3.terrain.heightmap.AbstractHeightMap;
  571. import com.jme3.terrain.geomipmap.TerrainQuad;
  572. import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
  573. import com.jme3.terrain.heightmap.HillHeightMap; // for exercise 2
  574. import com.jme3.terrain.heightmap.ImageBasedHeightMap;
  575. import com.jme3.texture.Texture;
  576. import com.jme3.texture.Texture.WrapMode;
  577. import java.util.ArrayList;
  578. import java.util.List;</p>
  579. </div>
  580. <div class="paragraph">
  581. <p>/** Sample 10 - How to create fast-rendering terrains from heightmaps,
  582. and how to use texture splatting to make the terrain look good. */
  583. public class HelloTerrain extends SimpleApplication {</p>
  584. </div>
  585. <div class="literalblock">
  586. <div class="content">
  587. <pre>private TerrainQuad terrain;
  588. Material mat_terrain;</pre>
  589. </div>
  590. </div>
  591. <div class="literalblock">
  592. <div class="content">
  593. <pre>public static void main(String[] args) {
  594. HelloTerrain app = new HelloTerrain();
  595. app.start();
  596. }</pre>
  597. </div>
  598. </div>
  599. <div class="literalblock">
  600. <div class="content">
  601. <pre>@Override
  602. public void simpleInitApp() {
  603. flyCam.setMoveSpeed(50);</pre>
  604. </div>
  605. </div>
  606. <div class="literalblock">
  607. <div class="content">
  608. <pre>/** 1. Create terrain material and load four textures into it. */
  609. mat_terrain = new Material(assetManager,
  610. "Common/MatDefs/Terrain/Terrain.j3md");</pre>
  611. </div>
  612. </div>
  613. <div class="literalblock">
  614. <div class="content">
  615. <pre>/** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
  616. mat_terrain.setTexture("Alpha", assetManager.loadTexture(
  617. "Textures/Terrain/splat/alphamap.png"));</pre>
  618. </div>
  619. </div>
  620. <div class="literalblock">
  621. <div class="content">
  622. <pre>/** 1.2) Add GRASS texture into the red layer (Tex1). */
  623. Texture grass = assetManager.loadTexture(
  624. "Textures/Terrain/splat/grass.jpg");
  625. grass.setWrap(WrapMode.Repeat);
  626. mat_terrain.setTexture("Tex1", grass);
  627. mat_terrain.setFloat("Tex1Scale", 64f);</pre>
  628. </div>
  629. </div>
  630. <div class="literalblock">
  631. <div class="content">
  632. <pre>/** 1.3) Add DIRT texture into the green layer (Tex2) */
  633. Texture dirt = assetManager.loadTexture(
  634. "Textures/Terrain/splat/dirt.jpg");
  635. dirt.setWrap(WrapMode.Repeat);
  636. mat_terrain.setTexture("Tex2", dirt);
  637. mat_terrain.setFloat("Tex2Scale", 32f);</pre>
  638. </div>
  639. </div>
  640. <div class="literalblock">
  641. <div class="content">
  642. <pre>/** 1.4) Add ROAD texture into the blue layer (Tex3) */
  643. Texture rock = assetManager.loadTexture(
  644. "Textures/Terrain/splat/road.jpg");
  645. rock.setWrap(WrapMode.Repeat);
  646. mat_terrain.setTexture("Tex3", rock);
  647. mat_terrain.setFloat("Tex3Scale", 128f);</pre>
  648. </div>
  649. </div>
  650. <div class="literalblock">
  651. <div class="content">
  652. <pre>/** 2. Create the height map */
  653. AbstractHeightMap heightmap = null;
  654. Texture heightMapImage = assetManager.loadTexture(
  655. "Textures/Terrain/splat/mountains512.png");
  656. heightmap = new ImageBasedHeightMap(heightMapImage.getImage());
  657. heightmap.load();</pre>
  658. </div>
  659. </div>
  660. <div class="literalblock">
  661. <div class="content">
  662. <pre>/** 3. We have prepared material and heightmap.
  663. * Now we create the actual terrain:
  664. * 3.1) Create a TerrainQuad and name it "my terrain".
  665. * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
  666. * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
  667. * 3.4) As LOD step scale we supply Vector3f(1,1,1).
  668. * 3.5) We supply the prepared heightmap itself.
  669. */
  670. int patchSize = 65;
  671. terrain = new TerrainQuad("my terrain", patchSize, 513, heightmap.getHeightMap());</pre>
  672. </div>
  673. </div>
  674. <div class="literalblock">
  675. <div class="content">
  676. <pre>/** 4. We give the terrain its material, position &amp; scale it, and attach it. */
  677. terrain.setMaterial(mat_terrain);
  678. terrain.setLocalTranslation(0, -100, 0);
  679. terrain.setLocalScale(2f, 1f, 2f);
  680. rootNode.attachChild(terrain);</pre>
  681. </div>
  682. </div>
  683. <div class="literalblock">
  684. <div class="content">
  685. <pre> /** 5. The LOD (level of detail) depends on were the camera is: */
  686. TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
  687. terrain.addControl(control);
  688. }
  689. }----
  690. When you run this sample you should see a landscape with dirt mountains, grass plains, plus some winding roads in between.</pre>
  691. </div>
  692. </div>
  693. </div>
  694. </div>
  695. <div class="sect1">
  696. <h2 id="what-is-a-heightmap">What is a Heightmap?</h2>
  697. <div class="sectionbody">
  698. <div class="paragraph">
  699. <p>Heightmaps are an efficient way of representing the shape of a hilly landscape. Not every pixel of the landscape is stored, instead, a grid of sample values is used to outline the terrain height at certain points. The heights between the samples is interpolated.</p>
  700. </div>
  701. <div class="paragraph">
  702. <p>In Java, a heightmap is a float array containing height values between 0f and 255f. Here is a very simple example of a terrain generated from a heightmap with 5x5=25 height values.</p>
  703. </div>
  704. <div class="paragraph">
  705. <p><span class="image"><img src="images/jme2/terrain-from-float-array.png" alt="terrain-from-float-array.png" height=""></span></p>
  706. </div>
  707. <div class="paragraph">
  708. <p>Important things to note:</p>
  709. </div>
  710. <div class="ulist">
  711. <ul>
  712. <li>
  713. <p>Low values (e.g. 0 or 50) are valeys.</p>
  714. </li>
  715. <li>
  716. <p>High values (e.g. 200, 255) are hills.</p>
  717. </li>
  718. <li>
  719. <p>The heightmap only specifies a few points, and the engine interpolates the rest. Interpolation is more efficient than creating a model with several millions vertices.</p>
  720. </li>
  721. </ul>
  722. </div>
  723. <div class="paragraph">
  724. <p>When looking at Java data types to hold an array of floats between 0 and 255, the Image class comes to mind. Storing a terrain&#8217;s height values as a grayscale image has one big advantage: The outcome is a very userfriendly, like a topographical map:</p>
  725. </div>
  726. <div class="ulist">
  727. <ul>
  728. <li>
  729. <p>Low values (e.g. 0 or 50) are dark gray – these are valleys.</p>
  730. </li>
  731. <li>
  732. <p>High values (e.g. 200, 255) are light grays – these are hills.</p>
  733. </li>
  734. </ul>
  735. </div>
  736. <div class="paragraph">
  737. <p>Look at the next screenshot: In the top left you see a 128x128 grayscale image (heightmap) that was used as a base to generate the depicted terrain. To make the hilly shape better visible, the mountain tops are colored white, valleys brown, and the areas inbetween green:</p>
  738. </div>
  739. <div class="paragraph">
  740. <p><span class="image"><img src="images/jme2/terrain-from-heightmap.png" alt="terrain-from-heightmap.png" height=""></span>}</p>
  741. </div>
  742. <div class="paragraph">
  743. <p>In a real game, you will want to use more complex and smoother terrains than the simple heightmaps shown here. Heightmaps typically have square sizes of 512x512 or 1024x1024, and contain hundred thousands to 1 million height values. No matter which size, the concept is the same as described here.</p>
  744. </div>
  745. <div class="sect2">
  746. <h3 id="looking-at-the-heightmap-code">Looking at the Heightmap Code</h3>
  747. <div class="imageblock" style="text-align: right">
  748. <div class="content">
  749. <img src="images/http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/mountains512.png" alt="mountains512.png" height="128">
  750. </div>
  751. </div>
  752. <div class="paragraph">
  753. <p>The first step of terrain creation is the heightmap. You can create one yourself in any standard graphic application. Make sure it has the following properties:</p>
  754. </div>
  755. <div class="ulist">
  756. <ul>
  757. <li>
  758. <p>The size must be square, and a power of two.</p>
  759. <div class="ulist">
  760. <ul>
  761. <li>
  762. <p>Examples: 128x128, 256x256, 512x512, 1024x1024</p>
  763. </li>
  764. </ul>
  765. </div>
  766. </li>
  767. <li>
  768. <p>Color mode must be 255 grayscales.</p>
  769. <div class="ulist">
  770. <ul>
  771. <li>
  772. <p>Don&#8217;t supply a color image, it will be interpreted as grayscale, with possibly weird results.</p>
  773. </li>
  774. </ul>
  775. </div>
  776. </li>
  777. <li>
  778. <p>Save the map as a .jpg or .png image file</p>
  779. </li>
  780. </ul>
  781. </div>
  782. <div class="paragraph">
  783. <p>The file <code>mountains512.png</code> that you see here is a typical example of an image heightmap.</p>
  784. </div>
  785. <div class="paragraph">
  786. <p>Here is how you create the heightmap object in your jME code:</p>
  787. </div>
  788. <div class="olist arabic">
  789. <ol class="arabic">
  790. <li>
  791. <p>Create a Texture object.</p>
  792. </li>
  793. <li>
  794. <p>Load your prepared heightmap image into the texture object.</p>
  795. </li>
  796. <li>
  797. <p>Create an AbstractHeightmap object from an ImageBasedHeightMap.<br>
  798. It requires an image from a JME Texture.</p>
  799. </li>
  800. <li>
  801. <p>Load the heightmap.</p>
  802. </li>
  803. </ol>
  804. </div>
  805. <div class="listingblock">
  806. <div class="content">
  807. <pre class="CodeRay highlight"><code data-lang="java">---- AbstractHeightMap heightmap = <span class="predefined-constant">null</span>;
  808. Texture heightMapImage = assetManager.loadTexture(
  809. <span class="string"><span class="delimiter">&quot;</span><span class="content">Textures/Terrain/splat/mountains512.png</span><span class="delimiter">&quot;</span></span>);
  810. heightmap = <span class="keyword">new</span> ImageBasedHeightMap(heightMapImage.getImage());
  811. heightmap.load();
  812. ----</code></pre>
  813. </div>
  814. </div>
  815. </div>
  816. </div>
  817. </div>
  818. <div class="sect1">
  819. <h2 id="what-is-texture-splatting">What is Texture Splatting?</h2>
  820. <div class="sectionbody">
  821. <div class="paragraph">
  822. <p>Previously you learned how to create a material for a simple shape such as a cube. All sides of the cube have the same color. You can apply the same material to a terrain, but then you have one big meadow, one big rock desert, etc. This is not always what you want.</p>
  823. </div>
  824. <div class="paragraph">
  825. <p>Texture splatting allows you create a custom material, and “paint textures on it like with a “paint brush. This is very useful for terrains: As you see in the example here, you can paint a grass texture into the valleys, a dirt texture onto the mountains, and free-form roads inbetween.</p>
  826. </div>
  827. <div class="paragraph">
  828. <p><a href="sdk/terrain_editor.html">TerrainEditor plugin</a><a href="sdk/terrain_editor.html">TerrainEditor plugin</a></p>
  829. </div>
  830. <div class="paragraph">
  831. <p>Splat textures are based on the <code>Terrain.j3md</code> material defintion. If you open the Terrain.j3md file, and look in the Material Parameters section, you see that you have several texture layers to paint on: <code>Tex1</code>, <code>Tex2</code>, <code>Tex3</code>, etc.</p>
  832. </div>
  833. <div class="paragraph">
  834. <p>Before you can start painting, you have to make a few decisions:</p>
  835. </div>
  836. <div class="olist arabic">
  837. <ol class="arabic">
  838. <li>
  839. <p>Choose three textures. For example grass.jpg, dirt.jpg, and road.jpg.
  840. image::http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/road.jpg[road.jpg,with="64",height="64",align="right"]</p>
  841. </li>
  842. </ol>
  843. </div>
  844. <div class="imageblock" style="text-align: right">
  845. <div class="content">
  846. <img src="images/http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/dirt.jpg" alt="dirt.jpg" height="64">
  847. </div>
  848. </div>
  849. <div class="imageblock" style="text-align: right">
  850. <div class="content">
  851. <img src="images/http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/grass.jpg" alt="grass.jpg" height="64">
  852. </div>
  853. </div>
  854. <div class="olist arabic">
  855. <ol class="arabic">
  856. <li>
  857. <p>You “paint three texture layers by using three colors: Red, blue and, green. You arbitrarily decide that…</p>
  858. <div class="olist loweralpha">
  859. <ol class="loweralpha" type="a">
  860. <li>
  861. <p>Red is grass – red is layer <code>Tex1</code>, so put the grass texture into Tex1.</p>
  862. </li>
  863. <li>
  864. <p>Green is dirt – green is layer <code>Tex2</code>, so put the dirt texture into Tex2.</p>
  865. </li>
  866. <li>
  867. <p>Blue is roads – blue is layer <code>Tex3</code>, so put the roads texture into Tex3.</p>
  868. </li>
  869. </ol>
  870. </div>
  871. </li>
  872. </ol>
  873. </div>
  874. <div class="paragraph">
  875. <p>Now you start painting the texture:</p>
  876. </div>
  877. <div class="olist arabic">
  878. <ol class="arabic">
  879. <li>
  880. <p>Make a copy of your terrains heightmap, <code>mountains512.png</code>. You want it as a reference for the shape of the landscape.</p>
  881. </li>
  882. <li>
  883. <p>Name the copy <code>alphamap.png</code>.</p>
  884. </li>
  885. <li>
  886. <p>Open <code>alphamap.png</code> in a graphic editor and switch the image mode to color image.</p>
  887. <div class="olist loweralpha">
  888. <ol class="loweralpha" type="a">
  889. <li>
  890. <p>Paint the black valleys red – this will be the grass.</p>
  891. </li>
  892. <li>
  893. <p>Paint the white hills green – this will be the dirt of the mountains.</p>
  894. </li>
  895. <li>
  896. <p>Paint blue lines where you want roads to criss-cross the landscape.</p>
  897. </li>
  898. </ol>
  899. </div>
  900. </li>
  901. <li>
  902. <p>The end result should look similar to this:</p>
  903. </li>
  904. </ol>
  905. </div>
  906. <div class="paragraph">
  907. <p><span class="image"><img src="images/http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/mountains512.png" alt="mountains512.png" height="64"></span> ⇒ <span class="image"><img src="images/http///jmonkeyengine.googlecode.com/svn/trunk/engine/test-data/Textures/Terrain/splat/alphamap.png" alt="alphamap.png" height="64"></span></p>
  908. </div>
  909. <div class="sect2">
  910. <h3 id="looking-at-the-texturing-code">Looking at the Texturing Code</h3>
  911. <div class="paragraph">
  912. <p>As usual, you create a Material object. Base it on the Material Definition <code>Terrain.j3md</code> that is included in the jME3 framework.</p>
  913. </div>
  914. <div class="listingblock">
  915. <div class="content">
  916. <pre class="CodeRay highlight"><code data-lang="java">----Material mat_terrain = <span class="keyword">new</span> Material(assetManager, <span class="string"><span class="delimiter">&quot;</span><span class="content">Common/MatDefs/Terrain/Terrain.j3md</span><span class="delimiter">&quot;</span></span>);----
  917. Load four textures into <span class="local-variable">this</span> material. The first one, <span class="error">`</span>Alpha<span class="error">`</span>, is the alphamap that you just created.</code></pre>
  918. </div>
  919. </div>
  920. <div class="listingblock">
  921. <div class="content">
  922. <pre class="CodeRay highlight"><code data-lang="java">----mat_terrain.setTexture(<span class="string"><span class="delimiter">&quot;</span><span class="content">Alpha</span><span class="delimiter">&quot;</span></span>,
  923. assetManager.loadTexture(<span class="string"><span class="delimiter">&quot;</span><span class="content">Textures/Terrain/splat/alphamap.png</span><span class="delimiter">&quot;</span></span>));----
  924. The three other textures are the layers that you have previously decided to paint: grass, dirt, and road. You create texture objects and load the three textures as usual. Note how you assign them to their respective texture layers (Tex1, Tex2, and Tex3) inside the Material!</code></pre>
  925. </div>
  926. </div>
  927. <div class="listingblock">
  928. <div class="content">
  929. <pre class="CodeRay highlight"><code data-lang="java">---- <span class="comment">/** 1.2) Add GRASS texture into the red layer (Tex1). */</span>
  930. Texture grass = assetManager.loadTexture(
  931. <span class="string"><span class="delimiter">&quot;</span><span class="content">Textures/Terrain/splat/grass.jpg</span><span class="delimiter">&quot;</span></span>);
  932. grass.setWrap(WrapMode.Repeat);
  933. mat_terrain.setTexture(<span class="string"><span class="delimiter">&quot;</span><span class="content">Tex1</span><span class="delimiter">&quot;</span></span>, grass);
  934. mat_terrain.setFloat(<span class="string"><span class="delimiter">&quot;</span><span class="content">Tex1Scale</span><span class="delimiter">&quot;</span></span>, <span class="float">64f</span>);</code></pre>
  935. </div>
  936. </div>
  937. <div class="literalblock">
  938. <div class="content">
  939. <pre>/** 1.3) Add DIRT texture into the green layer (Tex2) */
  940. Texture dirt = assetManager.loadTexture(
  941. "Textures/Terrain/splat/dirt.jpg");
  942. dirt.setWrap(WrapMode.Repeat);
  943. mat_terrain.setTexture("Tex2", dirt);
  944. mat_terrain.setFloat("Tex2Scale", 32f);</pre>
  945. </div>
  946. </div>
  947. <div class="literalblock">
  948. <div class="content">
  949. <pre>/** 1.4) Add ROAD texture into the blue layer (Tex3) */
  950. Texture rock = assetManager.loadTexture(
  951. "Textures/Terrain/splat/road.jpg");
  952. rock.setWrap(WrapMode.Repeat);
  953. mat_terrain.setTexture("Tex3", rock);
  954. mat_terrain.setFloat("Tex3Scale", 128f);</pre>
  955. </div>
  956. </div>
  957. <div class="listingblock">
  958. <div class="content">
  959. <pre>The individual texture scales (e.g. `mat_terrain.setFloat(“Tex3Scale, 128f);`) depend on the size of the textures you use.
  960. * You can tell you picked too small a scale if, for example, your road tiles appear like tiny grains of sand.
  961. * You can tell you picked too big a scale if, for example, the blades of grass look like twigs.
  962. Use `setWrap(WrapMode.Repeat)` to make the small texture fill the wide area. If the repetition is too visible, try adjusting the respective `Tex*Scale` value.
  963. == What is a Terrain?
  964. Internally, the generated terrain mesh is broken down into tiles and blocks. This is an optimization to make culling easier. You do not need to worry about “tiles and blocks too much, just use recommended values for now – 64 is a good start.
  965. Let's assume you want to generate a 512x512 terrain. You already have created the heightmap object. Here are the steps that you perform everytime you create a new terrain.
  966. Create a TerrainQuad with the following arguments:
  967. . Specify a name: E.g. `my terrain`.
  968. . Specify tile size: You want to terrain tiles of size 64x64, so you supply 64+1 = 65.
  969. ** In general, 64 is a good starting value for terrain tiles.
  970. . Specify block size: Since you prepared a heightmap of size 512x512, you supply 512+1 = 513.
  971. ** If you supply a block size of 2x the heightmap size (1024+1=1025), you get a stretched out, wider, flatter terrain.
  972. ** If you supply a block size 1/2 the heightmap size (256+1=257), you get a smaller, more detailed terrain.
  973. . Supply the 512x512 heightmap object that you created.
  974. === Looking at the Terrain Code
  975. Here's the code:
  976. [source]
  977. ----terrain = new TerrainQuad(
  978. "my terrain", // name
  979. 65, // tile size
  980. 513, // block size
  981. heightmap.getHeightMap()); // heightmap</pre>
  982. </div>
  983. </div>
  984. <div class="paragraph">
  985. <p>You have created the terrain object.</p>
  986. </div>
  987. <div class="olist arabic">
  988. <ol class="arabic">
  989. <li>
  990. <p>Remember to apply the created material:</p>
  991. <div class="listingblock">
  992. <div class="content">
  993. <pre class="CodeRay highlight"><code data-lang="java">----terrain.setMaterial(mat_terrain);----</code></pre>
  994. </div>
  995. </div>
  996. </li>
  997. <li>
  998. <p>Remember to attach the terrain to the rootNode.</p>
  999. <div class="listingblock">
  1000. <div class="content">
  1001. <pre class="CodeRay highlight"><code data-lang="java">----rootNode.attachChild(terrain);</code></pre>
  1002. </div>
  1003. </div>
  1004. </li>
  1005. </ol>
  1006. </div>
  1007. <div class="listingblock">
  1008. <div class="content">
  1009. <pre>. If needed, scale and translate the terrain object, just like any other Spatial.
  1010. *Tip:* Terrain.j3md is an unshaded material definition, so you do not need a light source. You can also use TerrainLighting.j3md plus a light, if you want a shaded terrain.
  1011. == What is LOD (Level of Detail)?
  1012. JME3 includes an optimization that adjusts the level of detail (LOD) of the rendered terrain depending on how close or far the camera is.
  1013. [source,java]</pre>
  1014. </div>
  1015. </div>
  1016. <div class="literalblock">
  1017. <div class="content">
  1018. <pre>TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
  1019. terrain.addControl(control);</pre>
  1020. </div>
  1021. </div>
  1022. <div class="listingblock">
  1023. <div class="content">
  1024. <pre>Close parts of the terrain are rendered in full detail. Terrain parts that are further away are not clearly visible anyway, and JME3 improves performance by rendering them less detailed. This way you can afford to load huge terrains with no penalty caused by invisible details.
  1025. == Exercises
  1026. === Exercise 1: Texture Layers
  1027. What happens when you swap two layers, for example `Tex1` and `Tex2`?
  1028. [source,java]</pre>
  1029. </div>
  1030. </div>
  1031. <div class="paragraph">
  1032. <p>&#8230;&#8203;
  1033. mat_terrain.setTexture("Tex2", grass);
  1034. &#8230;&#8203;
  1035. mat_terrain.setTexture("Tex1", dirt);</p>
  1036. </div>
  1037. <div class="listingblock">
  1038. <div class="content">
  1039. <pre>You see it's easier to swap layers in the code, than to change the colors in the alphamap.
  1040. === Exercise 2: Randomized Terrains
  1041. The following three lines generate the heightmap object based on your user-defined image:
  1042. [source,java]
  1043. ---- AbstractHeightMap heightmap = null;
  1044. Texture heightMapImage = assetManager.loadTexture(
  1045. "Textures/Terrain/splat/mountains512.png");
  1046. heightmap = new ImageBasedHeightMap(heightMapImage.getImage());----
  1047. Instead, you can also let JME3 generate a random landscape for you:
  1048. . What result do you get when you replace the above three heightmap lines by the following lines and run the sample?
  1049. [source,java]</pre>
  1050. </div>
  1051. </div>
  1052. <div class="paragraph">
  1053. <p>HillHeightMap heightmap = null;
  1054. HillHeightMap.NORMALIZE_RANGE = 100; // optional
  1055. try {
  1056. heightmap = new HillHeightMap(513, 1000, 50, 100, (byte) 3); // byte 3 is a random seed
  1057. } catch (Exception ex) {
  1058. ex.printStackTrace();
  1059. }----
  1060. . Change one parameter at a time, and the run the sample again. Note the differences. Can you find out which of the values has which effect on the generated terrain (look at the javadoc also)?
  1061. <strong> Which value controls the size?
  1062. </strong>* What happens if the size is not a square number +1 ?</p>
  1063. </div>
  1064. <div class="ulist">
  1065. <ul>
  1066. <li>
  1067. <p>Which value controls the number of hills generated?</p>
  1068. </li>
  1069. <li>
  1070. <p>Which values control the size and steepness of the hills?</p>
  1071. <div class="ulist">
  1072. <ul>
  1073. <li>
  1074. <p>What happens if the min is bigger than or equal to max?</p>
  1075. </li>
  1076. <li>
  1077. <p>What happens if both min and max are small values (e.g. 10/20)?</p>
  1078. </li>
  1079. <li>
  1080. <p>What happens if both min and max are large values (e.g. 1000/1500)?</p>
  1081. </li>
  1082. <li>
  1083. <p>What happens if min and max are very close(e.g. 1000/1001, 20/21)? Very far apart (e.g. 10/1000)?</p>
  1084. </li>
  1085. </ul>
  1086. </div>
  1087. </li>
  1088. </ul>
  1089. </div>
  1090. <div class="paragraph">
  1091. <p>You see the variety of hilly landscapes that can be generated using this method.</p>
  1092. </div>
  1093. </div>
  1094. <div class="sect2">
  1095. <h3 id="exercise-3-solid-terrains">Exercise 3: Solid Terrains</h3>
  1096. <div class="paragraph">
  1097. <p>Can you combine what you learned here and in <a href="hello_collision.html">Hello Collision</a>, and <a href="jme3/advanced/terrain_collision.html">make the terrain solid</a>?</p>
  1098. </div>
  1099. </div>
  1100. </div>
  1101. </div>
  1102. <div class="sect1">
  1103. <h2 id="conclusion">Conclusion</h2>
  1104. <div class="sectionbody">
  1105. <div class="paragraph">
  1106. <p>You have learned how to create terrains that are more efficient than loading one giant model. You know how to generate random or create handmade heightmaps. You can add a LOD control to render large terrains faster. You are aware that you can combine what you learned about collision detection to make the terrain solid to a physical player. You are also able to texture a terrain “like a boss using layered Materials and texture splatting. You are aware that the jMonkeyEngine SDK provides a TerrainEditor that helps with most of these manual tasks.</p>
  1107. </div>
  1108. <div class="paragraph">
  1109. <p>Do you want to hear your players say “ouch! when they bump into a wall or fall off a hill? Continue with learning <a href="hello_audio.html">how to add sound</a> to your game.</p>
  1110. </div>
  1111. <hr>
  1112. <div class="paragraph">
  1113. <p>See also:</p>
  1114. </div>
  1115. <div class="ulist">
  1116. <ul>
  1117. <li>
  1118. <p><a href="jme3/advanced/terrain_collision.html">Terrain Collision</a>
  1119. &lt;tags&gt;&lt;tag target="beginner" /&gt;&lt;tag target="heightmap" /&gt;&lt;tag target="documentation" /&gt;&lt;tag target="terrain" /&gt;&lt;tag target="texture" /&gt;&lt;/tags&gt;</p>
  1120. </li>
  1121. </ul>
  1122. </div>
  1123. </div>
  1124. </div>
  1125. </div>
  1126. <div id="footer">
  1127. <div id="footer-text">
  1128. Last updated 2016-05-21 23:44:18 UTC
  1129. </div>
  1130. </div>
  1131. </body>
  1132. </html>