charts.html 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1">
  6. <title>JME 3 Tutorial - Visualizing 3D Charts :: jMonkeyEngine Docs</title>
  7. <link rel="canonical" href="https://wiki.jmonkeyengine.org/docs/3.8/contributions/tools/charts.html">
  8. <link rel="prev" href="navigation.html">
  9. <link rel="next" href="../projects/rise_of_mutants_project.html">
  10. <meta name="generator" content="Antora 3.0.1">
  11. <link rel="stylesheet" href="../../../../_/css/site.css">
  12. <meta property="og:image" content="https://wiki.jmonkeyengine.org/_/img/iconx128.png">
  13. <meta property="og:description" content="JME 3 Tutorial - Visualizing 3D Charts">
  14. <meta property="og:title" content="jMonkeyEngine Docs">
  15. <link rel="stylesheet" href="../../../../_/css/site-extra.css">
  16. <link rel="stylesheet" href="../../../../_/css/vendor/docsearch.min.css">
  17. <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css -->
  18. <link rel="icon" href="../../../../_/img/favicon.ico" type="image/x-icon">
  19. </head>
  20. <body class="article">
  21. <header class="header">
  22. <nav class="navbar">
  23. <div class="navbar-brand">
  24. <a class="navbar-item" href="https://wiki.jmonkeyengine.org">
  25. <img alt="" src="../../../../_/img/jme-logo.png" height="32" type="image/x-icon">
  26. </a>
  27. <div class="navbar-item hide-for-print">
  28. <input id="search-input" type="text" placeholder="Search docs">
  29. </div>
  30. <button class="navbar-burger" data-target="topbar-nav">
  31. <span></span>
  32. <span></span>
  33. <span></span>
  34. </button>
  35. </div>
  36. <div id="topbar-nav" class="navbar-menu">
  37. <div class="navbar-end">
  38. <div class="navbar-item theme-switch-wrapper">
  39. <label class="theme-switch" for="checkbox">
  40. <input type="checkbox" id="checkbox" />
  41. <div class="slider round"></div>
  42. </label>
  43. </div>
  44. <a class="navbar-item" href="https://github.com/jmonkeyengine/wiki">Github</a>
  45. </div>
  46. </div>
  47. </nav>
  48. </header>
  49. <div class="body">
  50. <div class="nav-container" data-component="docs" data-version="3.4">
  51. <aside class="nav">
  52. <div class="panels">
  53. <div class="nav-panel-menu is-active" data-panel="menu">
  54. <nav class="nav-menu">
  55. <h3 class="title"><a href="../../documentation.html">JME</a></h3>
  56. <ul class="nav-list">
  57. <li class="nav-item" data-depth="0">
  58. <ul class="nav-list">
  59. <li class="nav-item" data-depth="1">
  60. <a class="nav-link" href="../../documentation.html">Getting Started</a>
  61. </li>
  62. <li class="nav-item" data-depth="1">
  63. <a class="nav-link" href="https://javadoc.jmonkeyengine.org/v3.4.1-stable">JavaDoc</a>
  64. </li>
  65. <li class="nav-item" data-depth="1">
  66. <a class="nav-link" href="../../release.html">Release Guide</a>
  67. </li>
  68. </ul>
  69. </li>
  70. <li class="nav-item" data-depth="0">
  71. <ul class="nav-list">
  72. <li class="nav-item" data-depth="1">
  73. <button class="nav-item-toggle"></button>
  74. <a class="nav-link" href="../../tutorials/beginner/beginner.html">Beginner Tutorials</a>
  75. <ul class="nav-list">
  76. <li class="nav-item" data-depth="2">
  77. <a class="nav-link" href="../../tutorials/beginner/hello_simpleapplication.html">Hello SimpleApplication</a>
  78. </li>
  79. <li class="nav-item" data-depth="2">
  80. <a class="nav-link" href="../../tutorials/beginner/hello_node.html">Hello Node</a>
  81. </li>
  82. <li class="nav-item" data-depth="2">
  83. <a class="nav-link" href="../../tutorials/beginner/hello_asset.html">Hello Asset</a>
  84. </li>
  85. <li class="nav-item" data-depth="2">
  86. <a class="nav-link" href="../../tutorials/beginner/hello_main_event_loop.html">Hello Update Loop</a>
  87. </li>
  88. <li class="nav-item" data-depth="2">
  89. <a class="nav-link" href="../../tutorials/beginner/hello_input_system.html">Hello Input System</a>
  90. </li>
  91. <li class="nav-item" data-depth="2">
  92. <a class="nav-link" href="../../tutorials/beginner/hello_material.html">Hello Material</a>
  93. </li>
  94. <li class="nav-item" data-depth="2">
  95. <a class="nav-link" href="../../tutorials/beginner/hello_animation.html">Hello Animation</a>
  96. </li>
  97. <li class="nav-item" data-depth="2">
  98. <a class="nav-link" href="../../tutorials/beginner/hello_picking.html">Hello Picking</a>
  99. </li>
  100. <li class="nav-item" data-depth="2">
  101. <a class="nav-link" href="../../tutorials/beginner/hello_collision.html">Hello Collision</a>
  102. </li>
  103. <li class="nav-item" data-depth="2">
  104. <a class="nav-link" href="../../tutorials/beginner/hello_terrain.html">Hello Terrain</a>
  105. </li>
  106. <li class="nav-item" data-depth="2">
  107. <a class="nav-link" href="../../tutorials/beginner/hello_audio.html">Hello Audio</a>
  108. </li>
  109. <li class="nav-item" data-depth="2">
  110. <a class="nav-link" href="../../tutorials/beginner/hello_effects.html">Hello Effects</a>
  111. </li>
  112. <li class="nav-item" data-depth="2">
  113. <a class="nav-link" href="../../tutorials/beginner/hello_physics.html">Hello Physics</a>
  114. </li>
  115. </ul>
  116. </li>
  117. <li class="nav-item" data-depth="1">
  118. <button class="nav-item-toggle"></button>
  119. <span class="nav-text">Key Concepts</span>
  120. <ul class="nav-list">
  121. <li class="nav-item" data-depth="2">
  122. <a class="nav-link" href="../../tutorials/concepts/best_practices.html">Best Practices</a>
  123. </li>
  124. <li class="nav-item" data-depth="2">
  125. <a class="nav-link" href="../../tutorials/concepts/optimization.html">Optimization</a>
  126. </li>
  127. <li class="nav-item" data-depth="2">
  128. <a class="nav-link" href="../../tutorials/concepts/faq.html">Frequently Asked Questions</a>
  129. </li>
  130. <li class="nav-item" data-depth="2">
  131. <a class="nav-link" href="../../tutorials/concepts/math_for_dummies.html">Math for Dummies</a>
  132. </li>
  133. <li class="nav-item" data-depth="2">
  134. <a class="nav-link" href="../../tutorials/concepts/math.html">Math overview</a>
  135. </li>
  136. <li class="nav-item" data-depth="2">
  137. <a class="nav-link" href="../../tutorials/concepts/math_cheet_sheet.html">3D math "cheat sheet"</a>
  138. </li>
  139. <li class="nav-item" data-depth="2">
  140. <a class="nav-link" href="../../tutorials/concepts/rotate.html">3-D Rotation</a>
  141. </li>
  142. <li class="nav-item" data-depth="2">
  143. <a class="nav-link" href="../../tutorials/concepts/math_video_tutorials.html">Math video tutorial series</a>
  144. </li>
  145. <li class="nav-item" data-depth="2">
  146. <a class="nav-link" href="../../tutorials/concepts/multi-media_asset_pipeline.html">Multi-Media Asset Pipeline</a>
  147. </li>
  148. <li class="nav-item" data-depth="2">
  149. <a class="nav-link" href="../../tutorials/concepts/the_scene_graph.html">The Scene Graph</a>
  150. </li>
  151. <li class="nav-item" data-depth="2">
  152. <a class="nav-link" href="../../tutorials/concepts/scenegraph_for_dummies.html">Scene Graph for Dummies</a>
  153. </li>
  154. <li class="nav-item" data-depth="2">
  155. <a class="nav-link" href="../../tutorials/concepts/terminology.html">3D Graphics Terminology</a>
  156. </li>
  157. <li class="nav-item" data-depth="2">
  158. <a class="nav-link" href="../../tutorials/concepts/transparency_sorting.html">Transparency Sorting</a>
  159. </li>
  160. </ul>
  161. </li>
  162. <li class="nav-item" data-depth="1">
  163. <button class="nav-item-toggle"></button>
  164. <span class="nav-text">Articles and How-to&#8217;s</span>
  165. <ul class="nav-list">
  166. <li class="nav-item" data-depth="2">
  167. <button class="nav-item-toggle"></button>
  168. <span class="nav-text">How to Model</span>
  169. <ul class="nav-list">
  170. <li class="nav-item" data-depth="3">
  171. <a class="nav-link" href="../../tutorials/how-to/modeling/3dsmax/3dsmax.html">3dsmax</a>
  172. </li>
  173. <li class="nav-item" data-depth="3">
  174. <button class="nav-item-toggle"></button>
  175. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender.html">Blender</a>
  176. <ul class="nav-list">
  177. <li class="nav-item" data-depth="4">
  178. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_buffer_clearing.html">Buffer Clearing</a>
  179. </li>
  180. <li class="nav-item" data-depth="4">
  181. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_gltf.html">Export as GlTF</a>
  182. </li>
  183. <li class="nav-item" data-depth="4">
  184. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_ogre_export.html">Export as Ogre XML</a>
  185. </li>
  186. <li class="nav-item" data-depth="4">
  187. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_ogre_compatibility.html">Ogre Compatibility</a>
  188. </li>
  189. <li class="nav-item" data-depth="4">
  190. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/makehuman.html">MakeHuman</a>
  191. </li>
  192. <li class="nav-item" data-depth="4">
  193. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/makehuman_blender_ogrexml_toolchain.html">MakeHuman toolchain</a>
  194. </li>
  195. </ul>
  196. </li>
  197. </ul>
  198. </li>
  199. <li class="nav-item" data-depth="2">
  200. <button class="nav-item-toggle"></button>
  201. <span class="nav-text">How to Animate</span>
  202. <ul class="nav-list">
  203. <li class="nav-item" data-depth="3">
  204. <button class="nav-item-toggle"></button>
  205. <span class="nav-text">Mixamo</span>
  206. <ul class="nav-list">
  207. <li class="nav-item" data-depth="4">
  208. <a class="nav-link" href="../../tutorials/how-to/modeling/blender/mixamo.html">Blender Models</a>
  209. </li>
  210. <li class="nav-item" data-depth="4">
  211. <button class="nav-item-toggle"></button>
  212. <span class="nav-text">Video</span>
  213. <ul class="nav-list">
  214. <li class="nav-item" data-depth="5">
  215. <a class="nav-link" href="https://youtu.be/jHgAgTWIers?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 1- Download Model</a>
  216. </li>
  217. <li class="nav-item" data-depth="5">
  218. <a class="nav-link" href="https://youtu.be/GQJSrOpNQwI?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 2- Rig and Animate</a>
  219. </li>
  220. <li class="nav-item" data-depth="5">
  221. <a class="nav-link" href="https://youtu.be/JzRe2Dxbcmc?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 3- Import to JME</a>
  222. </li>
  223. <li class="nav-item" data-depth="5">
  224. <a class="nav-link" href="https://youtu.be/8wwDRDJop7k?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 4- Play Animation</a>
  225. </li>
  226. </ul>
  227. </li>
  228. </ul>
  229. </li>
  230. </ul>
  231. </li>
  232. <li class="nav-item" data-depth="2">
  233. <a class="nav-link" href="../../tutorials/how-to/debugging.html">Debugging with Wireframes</a>
  234. </li>
  235. <li class="nav-item" data-depth="2">
  236. <a class="nav-link" href="../../tutorials/how-to/util/free_skymaps.html">How to create free skymaps</a>
  237. </li>
  238. <li class="nav-item" data-depth="2">
  239. <button class="nav-item-toggle"></button>
  240. <span class="nav-text">Java Tips</span>
  241. <ul class="nav-list">
  242. <li class="nav-item" data-depth="3">
  243. <a class="nav-link" href="../../tutorials/how-to/java/localization.html">Localization</a>
  244. </li>
  245. <li class="nav-item" data-depth="3">
  246. <a class="nav-link" href="../../tutorials/how-to/java/swing_canvas.html">Swing Canvas</a>
  247. </li>
  248. <li class="nav-item" data-depth="3">
  249. <a class="nav-link" href="../../tutorials/how-to/java/logging.html">Logging</a>
  250. </li>
  251. <li class="nav-item" data-depth="3">
  252. <a class="nav-link" href="../../tutorials/how-to/java/read_graphic_card_capabilites.html">Read Graphics Capabilities</a>
  253. </li>
  254. </ul>
  255. </li>
  256. <li class="nav-item" data-depth="2">
  257. <button class="nav-item-toggle"></button>
  258. <span class="nav-text">Articles</span>
  259. <ul class="nav-list">
  260. <li class="nav-item" data-depth="3">
  261. <button class="nav-item-toggle"></button>
  262. <span class="nav-text">Physically Based Rendering</span>
  263. <ul class="nav-list">
  264. <li class="nav-item" data-depth="4">
  265. <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part1.html">PBR – Part one</a>
  266. </li>
  267. <li class="nav-item" data-depth="4">
  268. <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part2.html">PBR – Part two</a>
  269. </li>
  270. <li class="nav-item" data-depth="4">
  271. <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part3.html">PBR – Part three</a>
  272. </li>
  273. </ul>
  274. </li>
  275. </ul>
  276. </li>
  277. </ul>
  278. </li>
  279. </ul>
  280. </li>
  281. <li class="nav-item" data-depth="0">
  282. <ul class="nav-list">
  283. <li class="nav-item" data-depth="1">
  284. <button class="nav-item-toggle"></button>
  285. <span class="nav-text">Core Engine</span>
  286. <ul class="nav-list">
  287. <li class="nav-item" data-depth="2">
  288. <a class="nav-link" href="../../core/app/simpleapplication.html">SimpleApplication</a>
  289. </li>
  290. <li class="nav-item" data-depth="2">
  291. <a class="nav-link" href="../../core/system/appsettings.html">AppSettings</a>
  292. </li>
  293. </ul>
  294. </li>
  295. <li class="nav-item" data-depth="1">
  296. <button class="nav-item-toggle"></button>
  297. <span class="nav-text">Controlling Game Logic</span>
  298. <ul class="nav-list">
  299. <li class="nav-item" data-depth="2">
  300. <a class="nav-link" href="../../core/app/update_loop.html">Update Loop</a>
  301. </li>
  302. <li class="nav-item" data-depth="2">
  303. <a class="nav-link" href="../../core/app/state/application_states.html">Application States</a>
  304. </li>
  305. <li class="nav-item" data-depth="2">
  306. <button class="nav-item-toggle"></button>
  307. <a class="nav-link" href="../../core/scene/control/custom_controls.html">Custom Controls</a>
  308. <ul class="nav-list">
  309. <li class="nav-item" data-depth="3">
  310. <button class="nav-item-toggle"></button>
  311. <span class="nav-text">Video</span>
  312. <ul class="nav-list">
  313. <li class="nav-item" data-depth="4">
  314. <a class="nav-link" href="https://www.youtube.com/watch?v=MNDiZ9YHIpM">Control any scene node</a>
  315. </li>
  316. <li class="nav-item" data-depth="4">
  317. <a class="nav-link" href="https://www.youtube.com/watch?v=-OzRZscLlHY">Control a character</a>
  318. </li>
  319. <li class="nav-item" data-depth="4">
  320. <a class="nav-link" href="https://wiki.jmonkeyengine.org/Scenes/SDK-UsecaseDemo_1.zip">Video Source Code</a>
  321. </li>
  322. </ul>
  323. </li>
  324. </ul>
  325. </li>
  326. <li class="nav-item" data-depth="2">
  327. <a class="nav-link" href="../../core/app/multithreading.html">Multithreading</a>
  328. </li>
  329. </ul>
  330. </li>
  331. <li class="nav-item" data-depth="1">
  332. <button class="nav-item-toggle"></button>
  333. <span class="nav-text">Scene Graph</span>
  334. <ul class="nav-list">
  335. <li class="nav-item" data-depth="2">
  336. <a class="nav-link" href="../../core/scene/traverse_scenegraph.html">Traverse SceneGraph</a>
  337. </li>
  338. <li class="nav-item" data-depth="2">
  339. <a class="nav-link" href="../../core/scene/spatial.html">Spatial: Node vs Geometry</a>
  340. </li>
  341. <li class="nav-item" data-depth="2">
  342. <button class="nav-item-toggle"></button>
  343. <a class="nav-link" href="../../core/scene/mesh.html">Mesh</a>
  344. <ul class="nav-list">
  345. <li class="nav-item" data-depth="3">
  346. <a class="nav-link" href="../../core/scene/custom_meshes.html">Custom Meshes</a>
  347. </li>
  348. <li class="nav-item" data-depth="3">
  349. <a class="nav-link" href="../../core/scene/shape/shape.html">Shape</a>
  350. </li>
  351. <li class="nav-item" data-depth="3">
  352. <a class="nav-link" href="../../core/scene/3d_models.html">3D Models</a>
  353. </li>
  354. </ul>
  355. </li>
  356. <li class="nav-item" data-depth="2">
  357. <a class="nav-link" href="../../core/asset/asset_manager.html">Asset Manager</a>
  358. </li>
  359. <li class="nav-item" data-depth="2">
  360. <a class="nav-link" href="../../core/export/save_and_load.html">Saving and Loading Nodes</a>
  361. </li>
  362. <li class="nav-item" data-depth="2">
  363. <a class="nav-link" href="../../core/collision/collision_and_intersection.html">Collision and Intersection</a>
  364. </li>
  365. <li class="nav-item" data-depth="2">
  366. <a class="nav-link" href="../../core/scene/control/level_of_detail.html">Level of Detail</a>
  367. </li>
  368. </ul>
  369. </li>
  370. <li class="nav-item" data-depth="1">
  371. <button class="nav-item-toggle"></button>
  372. <span class="nav-text">Animation, Scene</span>
  373. <ul class="nav-list">
  374. <li class="nav-item" data-depth="2">
  375. <a class="nav-link" href="../../core/animation/animation.html">Animation-Old</a>
  376. </li>
  377. <li class="nav-item" data-depth="2">
  378. <a class="nav-link" href="../../core/cinematic/cinematics.html">Cinematics (cutscenes, fake destruction physics)</a>
  379. </li>
  380. <li class="nav-item" data-depth="2">
  381. <a class="nav-link" href="../../core/cinematic/motionpath.html">MotionPaths and Waypoints</a>
  382. </li>
  383. </ul>
  384. </li>
  385. <li class="nav-item" data-depth="1">
  386. <button class="nav-item-toggle"></button>
  387. <span class="nav-text">Material, Light, Shadow</span>
  388. <ul class="nav-list">
  389. <li class="nav-item" data-depth="2">
  390. <a class="nav-link" href="../../core/material/how_to_use_materials.html">How to use Materials</a>
  391. </li>
  392. <li class="nav-item" data-depth="2">
  393. <a class="nav-link" href="../../core/material/j3m_material_files.html">.j3m Material Files</a>
  394. </li>
  395. <li class="nav-item" data-depth="2">
  396. <a class="nav-link" href="../../core/material/material_definitions.html">.j3md Material Definitions</a>
  397. </li>
  398. <li class="nav-item" data-depth="2">
  399. <a class="nav-link" href="../../core/material/materials_overview.html">.j3md Properties</a>
  400. </li>
  401. <li class="nav-item" data-depth="2">
  402. <a class="nav-link" href="../../core/shader/jme3_shaders.html">Shaders and JME3</a>
  403. </li>
  404. <li class="nav-item" data-depth="2">
  405. <a class="nav-link" href="../../core/shader/jme3_shadernodes.html">Shader Node System</a>
  406. </li>
  407. <li class="nav-item" data-depth="2">
  408. <a class="nav-link" href="../../core/shader/shader_video_tutorials.html">Shader Video Tutorials</a>
  409. </li>
  410. <li class="nav-item" data-depth="2">
  411. <a class="nav-link" href="../../core/light/light_and_shadow.html">Light and Shadow</a>
  412. </li>
  413. <li class="nav-item" data-depth="2">
  414. <a class="nav-link" href="../../core/texture/anisotropic_filtering.html">Anisotropic Filtering</a>
  415. </li>
  416. <li class="nav-item" data-depth="2">
  417. <a class="nav-link" href="../../core/system/jme3_srgbpipeline.html">Gamma Correction</a>
  418. </li>
  419. </ul>
  420. </li>
  421. <li class="nav-item" data-depth="1">
  422. <button class="nav-item-toggle"></button>
  423. <span class="nav-text">Audio, Video</span>
  424. <ul class="nav-list">
  425. <li class="nav-item" data-depth="2">
  426. <a class="nav-link" href="../../core/audio/audio.html">Playing Sounds</a>
  427. </li>
  428. <li class="nav-item" data-depth="2">
  429. <a class="nav-link" href="../../core/audio/audio_environment_presets.html">Audio Environment Presets</a>
  430. </li>
  431. <li class="nav-item" data-depth="2">
  432. <a class="nav-link" href="../../core/app/state/screenshots.html">Capture Screenshots</a>
  433. </li>
  434. <li class="nav-item" data-depth="2">
  435. <a class="nav-link" href="../../core/app/state/capture_audio_video_to_a_file.html">Capture Audio/Video</a>
  436. </li>
  437. </ul>
  438. </li>
  439. <li class="nav-item" data-depth="1">
  440. <button class="nav-item-toggle"></button>
  441. <span class="nav-text">Filter, Effect</span>
  442. <ul class="nav-list">
  443. <li class="nav-item" data-depth="2">
  444. <a class="nav-link" href="../../core/effect/effects_overview.html">Overview</a>
  445. </li>
  446. <li class="nav-item" data-depth="2">
  447. <a class="nav-link" href="../../core/effect/bloom_and_glow.html">Bloom and Glow</a>
  448. </li>
  449. <li class="nav-item" data-depth="2">
  450. <a class="nav-link" href="../../core/effect/particle_emitters.html">Particle Emitters</a>
  451. </li>
  452. </ul>
  453. </li>
  454. <li class="nav-item" data-depth="1">
  455. <button class="nav-item-toggle"></button>
  456. <span class="nav-text">Landscapes</span>
  457. <ul class="nav-list">
  458. <li class="nav-item" data-depth="2">
  459. <a class="nav-link" href="../../core/util/sky.html">Sky</a>
  460. </li>
  461. <li class="nav-item" data-depth="2">
  462. <a class="nav-link" href="../../core/terrain/terrain.html">Terrain (TerraMonkey)</a>
  463. </li>
  464. <li class="nav-item" data-depth="2">
  465. <a class="nav-link" href="../../core/collision/terrain_collision.html">Terrain Collision</a>
  466. </li>
  467. <li class="nav-item" data-depth="2">
  468. <a class="nav-link" href="../../core/effect/water.html">Simple Water</a>
  469. </li>
  470. <li class="nav-item" data-depth="2">
  471. <a class="nav-link" href="../../core/effect/post-processor_water.html">Post-Processor Water</a>
  472. </li>
  473. </ul>
  474. </li>
  475. <li class="nav-item" data-depth="1">
  476. <button class="nav-item-toggle"></button>
  477. <span class="nav-text">Camera</span>
  478. <ul class="nav-list">
  479. <li class="nav-item" data-depth="2">
  480. <a class="nav-link" href="../../core/renderer/camera.html">Camera</a>
  481. </li>
  482. <li class="nav-item" data-depth="2">
  483. <a class="nav-link" href="../../core/renderer/making_the_camera_follow_a_character.html">Follow a Character</a>
  484. </li>
  485. <li class="nav-item" data-depth="2">
  486. <a class="nav-link" href="../../core/renderer/remote-controlling_the_camera.html">Remote-Controlling</a>
  487. </li>
  488. <li class="nav-item" data-depth="2">
  489. <a class="nav-link" href="../../core/renderer/multiple_camera_views.html">Multiple Camera Views</a>
  490. </li>
  491. <li class="nav-item" data-depth="2">
  492. <a class="nav-link" href="../../core/renderer/jme3_renderbuckets.html">Render Buckets</a>
  493. </li>
  494. </ul>
  495. </li>
  496. <li class="nav-item" data-depth="1">
  497. <button class="nav-item-toggle"></button>
  498. <span class="nav-text">User Interaction</span>
  499. <ul class="nav-list">
  500. <li class="nav-item" data-depth="2">
  501. <a class="nav-link" href="../../core/input/input_handling.html">Input Handling</a>
  502. </li>
  503. <li class="nav-item" data-depth="2">
  504. <a class="nav-link" href="../../core/input/combo_moves.html">Combo Moves</a>
  505. </li>
  506. <li class="nav-item" data-depth="2">
  507. <a class="nav-link" href="../../core/input/mouse_picking.html">Mouse Picking</a>
  508. </li>
  509. </ul>
  510. </li>
  511. <li class="nav-item" data-depth="1">
  512. <button class="nav-item-toggle"></button>
  513. <a class="nav-link" href="../../core/gui/topic_gui.html">Graphical User Interface</a>
  514. <ul class="nav-list">
  515. <li class="nav-item" data-depth="2">
  516. <button class="nav-item-toggle"></button>
  517. <span class="nav-text">Nifty GUI</span>
  518. <ul class="nav-list">
  519. <li class="nav-item" data-depth="3">
  520. <a class="nav-link" href="../../core/gui/nifty_gui.html">Integration Tutorial</a>
  521. </li>
  522. <li class="nav-item" data-depth="3">
  523. <a class="nav-link" href="../../core/gui/nifty_gui_best_practices.html">Best Practices</a>
  524. </li>
  525. <li class="nav-item" data-depth="3">
  526. <a class="nav-link" href="../../core/gui/nifty_gui_scenarios.html">Scenarios</a>
  527. </li>
  528. </ul>
  529. </li>
  530. <li class="nav-item" data-depth="2">
  531. <a class="nav-link" href="../../core/ui/hud.html">Head-Up Display (HUD)</a>
  532. </li>
  533. </ul>
  534. </li>
  535. <li class="nav-item" data-depth="1">
  536. <button class="nav-item-toggle"></button>
  537. <span class="nav-text">Virtual Reality</span>
  538. <ul class="nav-list">
  539. <li class="nav-item" data-depth="2">
  540. <a class="nav-link" href="../../core/vr/virtualreality.html">Virtual Reality</a>
  541. </li>
  542. <li class="nav-item" data-depth="2">
  543. <a class="nav-link" href="../../core/vr/virtualrealitycontrollers.html">Virtual Reality Controllers</a>
  544. </li>
  545. </ul>
  546. </li>
  547. </ul>
  548. </li>
  549. <li class="nav-item" data-depth="0">
  550. <ul class="nav-list">
  551. <li class="nav-item" data-depth="1">
  552. <button class="nav-item-toggle"></button>
  553. <a class="nav-link" href="../../physics/physics.html">Physics</a>
  554. <ul class="nav-list">
  555. <li class="nav-item" data-depth="2">
  556. <a class="nav-link" href="../../physics/bullet_multithreading.html">Multi-Threaded Physics</a>
  557. </li>
  558. <li class="nav-item" data-depth="2">
  559. <a class="nav-link" href="../../physics/collision/physics_listeners.html">Collision Detection</a>
  560. </li>
  561. <li class="nav-item" data-depth="2">
  562. <a class="nav-link" href="../../physics/joint/hinges_and_joints.html">Hinges and Joints</a>
  563. </li>
  564. <li class="nav-item" data-depth="2">
  565. <a class="nav-link" href="../../physics/control/walking_character.html">Walking Character</a>
  566. </li>
  567. <li class="nav-item" data-depth="2">
  568. <a class="nav-link" href="../../physics/control/ragdoll.html">Ragdoll</a>
  569. </li>
  570. <li class="nav-item" data-depth="2">
  571. <a class="nav-link" href="../../physics/control/vehicles.html">Vehicles</a>
  572. </li>
  573. <li class="nav-item" data-depth="2">
  574. <a class="nav-link" href="../../physics/control/softbody.html">Softbody</a>
  575. </li>
  576. <li class="nav-item" data-depth="2">
  577. <a class="nav-link" href="../../physics/bullet_pitfalls.html">Bullet Physics Pitfalls</a>
  578. </li>
  579. </ul>
  580. </li>
  581. </ul>
  582. </li>
  583. <li class="nav-item" data-depth="0">
  584. <ul class="nav-list">
  585. <li class="nav-item" data-depth="1">
  586. <button class="nav-item-toggle"></button>
  587. <span class="nav-text">Networking</span>
  588. <ul class="nav-list">
  589. <li class="nav-item" data-depth="2">
  590. <a class="nav-link" href="../../networking/networking.html">Networking (SpiderMonkey)</a>
  591. </li>
  592. <li class="nav-item" data-depth="2">
  593. <a class="nav-link" href="../../networking/headless_server.html">Headless Server</a>
  594. </li>
  595. <li class="nav-item" data-depth="2">
  596. <a class="nav-link" href="../../networking/monkey_zone.html">Multi-Player Demo Code</a>
  597. </li>
  598. <li class="nav-item" data-depth="2">
  599. <a class="nav-link" href="../../networking/networking_video_tutorials.html">Networking Video Tutorials</a>
  600. </li>
  601. </ul>
  602. </li>
  603. </ul>
  604. </li>
  605. <li class="nav-item" data-depth="0">
  606. <ul class="nav-list">
  607. <li class="nav-item" data-depth="1">
  608. <button class="nav-item-toggle"></button>
  609. <span class="nav-text">User Contributions</span>
  610. <ul class="nav-list">
  611. <li class="nav-item" data-depth="2">
  612. <a class="nav-link" href="../contributions.html">User Made Utilities</a>
  613. </li>
  614. <li class="nav-item" data-depth="2">
  615. <button class="nav-item-toggle"></button>
  616. <span class="nav-text">Shader</span>
  617. <ul class="nav-list">
  618. <li class="nav-item" data-depth="3">
  619. <a class="nav-link" href="../shader/shaderblow_project.html">ShaderBlow Project</a>
  620. </li>
  621. </ul>
  622. </li>
  623. <li class="nav-item" data-depth="2">
  624. <button class="nav-item-toggle"></button>
  625. <span class="nav-text">Landscapes</span>
  626. <ul class="nav-list">
  627. <li class="nav-item" data-depth="3">
  628. <a class="nav-link" href="../lanscapes/vegetationsystem/vegetationsystem.html">Vegetation System</a>
  629. </li>
  630. </ul>
  631. </li>
  632. <li class="nav-item" data-depth="2">
  633. <button class="nav-item-toggle"></button>
  634. <span class="nav-text">Networking</span>
  635. <ul class="nav-list">
  636. <li class="nav-item" data-depth="3">
  637. <a class="nav-link" href="../networking/open_game_finder.html">Open Game Finder</a>
  638. </li>
  639. </ul>
  640. </li>
  641. <li class="nav-item" data-depth="2">
  642. <button class="nav-item-toggle"></button>
  643. <span class="nav-text">Entity System</span>
  644. <ul class="nav-list">
  645. <li class="nav-item" data-depth="3">
  646. <a class="nav-link" href="#es/entitysystem.adoc">The Zay-ES Entity System</a>
  647. </li>
  648. </ul>
  649. </li>
  650. <li class="nav-item" data-depth="2">
  651. <button class="nav-item-toggle"></button>
  652. <span class="nav-text">Artificial Intelligence</span>
  653. <ul class="nav-list">
  654. <li class="nav-item" data-depth="3">
  655. <a class="nav-link" href="../ai/recast.html">Recast Navigation</a>
  656. </li>
  657. <li class="nav-item" data-depth="3">
  658. <a class="nav-link" href="../ai/building_recast.html">Updating and building Recast Native Bindings</a>
  659. </li>
  660. <li class="nav-item" data-depth="3">
  661. <a class="nav-link" href="../ai/monkey_brains.html">Monkey Brains</a>
  662. </li>
  663. <li class="nav-item" data-depth="3">
  664. <a class="nav-link" href="../ai/steer_behaviours.html">Steer Behaviours</a>
  665. </li>
  666. <li class="nav-item" data-depth="3">
  667. <a class="nav-link" href="../ai/jme3_ai.html">jME3 Artificial Intelligence</a>
  668. </li>
  669. </ul>
  670. </li>
  671. <li class="nav-item" data-depth="2">
  672. <button class="nav-item-toggle"></button>
  673. <a class="nav-link" href="../gui/topic_contributions_gui.html">GUI</a>
  674. <ul class="nav-list">
  675. <li class="nav-item" data-depth="3">
  676. <a class="nav-link" href="../contributions.html#lemur-gui-library">Lemur - a native jME3 GUI library with scene graph tools</a>
  677. </li>
  678. <li class="nav-item" data-depth="3">
  679. <a class="nav-link" href="../contributions.html#tonegodgui">tonegodGUI - a native jME3 GUI library</a>
  680. </li>
  681. <li class="nav-item" data-depth="3">
  682. <a class="nav-link" href="../contributions.html#immediate-graphical-user-interface">Immediate graphical user interface</a>
  683. </li>
  684. </ul>
  685. </li>
  686. <li class="nav-item" data-depth="2">
  687. <button class="nav-item-toggle"></button>
  688. <span class="nav-text">Tools</span>
  689. <ul class="nav-list">
  690. <li class="nav-item" data-depth="3">
  691. <a class="nav-link" href="navigation.html">Mercator Projection Tool (Marine Navigation)</a>
  692. </li>
  693. <li class="nav-item is-current-page" data-depth="3">
  694. <a class="nav-link" href="charts.html">Visualizing Maps in JME3 (Marine Charts)</a>
  695. </li>
  696. </ul>
  697. </li>
  698. <li class="nav-item" data-depth="2">
  699. <button class="nav-item-toggle"></button>
  700. <span class="nav-text">Projects</span>
  701. <ul class="nav-list">
  702. <li class="nav-item" data-depth="3">
  703. <a class="nav-link" href="../projects/rise_of_mutants_project.html">Rise of Mutants Project</a>
  704. </li>
  705. </ul>
  706. </li>
  707. </ul>
  708. </li>
  709. </ul>
  710. </li>
  711. <li class="nav-item" data-depth="0">
  712. <ul class="nav-list">
  713. <li class="nav-item" data-depth="1">
  714. <button class="nav-item-toggle"></button>
  715. <a class="nav-link" href="../../sdk/sdk.html">SDK</a>
  716. <ul class="nav-list">
  717. <li class="nav-item" data-depth="2">
  718. <button class="nav-item-toggle"></button>
  719. <span class="nav-text">Video Tutorials</span>
  720. <ul class="nav-list">
  721. <li class="nav-item" data-depth="3">
  722. <button class="nav-item-toggle"></button>
  723. <span class="nav-text">SDK Use Case Tutorials</span>
  724. <ul class="nav-list">
  725. <li class="nav-item" data-depth="4">
  726. <a class="nav-link" href="http://www.youtube.com/watch?v=-OzRZscLlHY">Demo 1 (Quixote demo)</a>
  727. </li>
  728. <li class="nav-item" data-depth="4">
  729. <a class="nav-link" href="http://www.youtube.com/watch?v=6-YWxD3JByE">Demo 2 (Models and Materials)</a>
  730. </li>
  731. </ul>
  732. </li>
  733. <li class="nav-item" data-depth="3">
  734. <button class="nav-item-toggle"></button>
  735. <span class="nav-text">SDK Tutorials</span>
  736. <ul class="nav-list">
  737. <li class="nav-item" data-depth="4">
  738. <a class="nav-link" href="http://www.youtube.com/watch?v=M1_0pbeyJzI">Basics</a>
  739. </li>
  740. <li class="nav-item" data-depth="4">
  741. <a class="nav-link" href="http://www.youtube.com/watch?v=nL7woH40i5c">Importing Models</a>
  742. </li>
  743. <li class="nav-item" data-depth="4">
  744. <a class="nav-link" href="http://www.youtube.com/watch?v=DUmgAjiNzhY">Dragging&amp;Dropping Nodes</a>
  745. </li>
  746. <li class="nav-item" data-depth="4">
  747. <a class="nav-link" href="http://www.youtube.com/watch?v=ntPAmtsQ6eM">Scene Composing</a>
  748. </li>
  749. <li class="nav-item" data-depth="4">
  750. <a class="nav-link" href="http://www.youtube.com/watch?v=zgPV3W6dD4s">Terrain with Collision Shape</a>
  751. </li>
  752. <li class="nav-item" data-depth="4">
  753. <a class="nav-link" href="http://www.youtube.com/watch?v=Feu3-mrpolc">Working with Materials</a>
  754. </li>
  755. <li class="nav-item" data-depth="4">
  756. <a class="nav-link" href="http://www.youtube.com/watch?v=MNDiZ9YHIpM">Custom Controls</a>
  757. </li>
  758. <li class="nav-item" data-depth="4">
  759. <a class="nav-link" href="http://www.youtube.com/watch?v=oZnssg8TBWQ">WebStart Deployment</a>
  760. </li>
  761. <li class="nav-item" data-depth="4">
  762. <a class="nav-link" href="http://www.youtube.com/watch?v=D7JM4VMKqPc">Animation and Effect TrackEditing</a>
  763. </li>
  764. </ul>
  765. </li>
  766. </ul>
  767. </li>
  768. <li class="nav-item" data-depth="2">
  769. <button class="nav-item-toggle"></button>
  770. <span class="nav-text">Getting Started</span>
  771. <ul class="nav-list">
  772. <li class="nav-item" data-depth="3">
  773. <a class="nav-link" href="../../sdk/update_center.html">Updating jMonkeyEngine SDK</a>
  774. </li>
  775. <li class="nav-item" data-depth="3">
  776. <a class="nav-link" href="../../sdk/troubleshooting.html">Troubleshooting</a>
  777. </li>
  778. </ul>
  779. </li>
  780. <li class="nav-item" data-depth="2">
  781. <button class="nav-item-toggle"></button>
  782. <span class="nav-text">Java Development Features</span>
  783. <ul class="nav-list">
  784. <li class="nav-item" data-depth="3">
  785. <a class="nav-link" href="../../sdk/project_creation.html">Project Creation</a>
  786. </li>
  787. <li class="nav-item" data-depth="3">
  788. <a class="nav-link" href="../../sdk/code_editor.html">Code Editor and Palette</a>
  789. </li>
  790. <li class="nav-item" data-depth="3">
  791. <a class="nav-link" href="../../sdk/version_control.html">File Version Control</a>
  792. </li>
  793. <li class="nav-item" data-depth="3">
  794. <a class="nav-link" href="../../sdk/debugging_profiling_testing.html">Debug, Profile, Test</a>
  795. </li>
  796. <li class="nav-item" data-depth="3">
  797. <button class="nav-item-toggle"></button>
  798. <a class="nav-link" href="../../sdk/application_deployment.html">Application Deployment</a>
  799. <ul class="nav-list">
  800. <li class="nav-item" data-depth="4">
  801. <a class="nav-link" href="../../sdk/default_build_script.html">Default Build Script</a>
  802. </li>
  803. <li class="nav-item" data-depth="4">
  804. <a class="nav-link" href="../../sdk/android.html">Android</a>
  805. </li>
  806. <li class="nav-item" data-depth="4">
  807. <a class="nav-link" href="../../sdk/android_cheat_sheet.html">Android Cheat Sheet</a>
  808. </li>
  809. <li class="nav-item" data-depth="4">
  810. <a class="nav-link" href="../../sdk/ios.html">iOS</a>
  811. </li>
  812. </ul>
  813. </li>
  814. </ul>
  815. </li>
  816. <li class="nav-item" data-depth="2">
  817. <button class="nav-item-toggle"></button>
  818. <span class="nav-text">Unique Features</span>
  819. <ul class="nav-list">
  820. <li class="nav-item" data-depth="3">
  821. <button class="nav-item-toggle"></button>
  822. <a class="nav-link" href="../../sdk/model_loader_and_viewer.html">Import, View, Convert Models</a>
  823. <ul class="nav-list">
  824. <li class="nav-item" data-depth="4">
  825. <a class="nav-link" href="../../sdk/asset_packs.html">Asset Packs</a>
  826. </li>
  827. </ul>
  828. </li>
  829. <li class="nav-item" data-depth="3">
  830. <a class="nav-link" href="../../sdk/scene_explorer.html">The SceneExplorer</a>
  831. </li>
  832. <li class="nav-item" data-depth="3">
  833. <a class="nav-link" href="../../sdk/scene_composer.html">Composing a Scene</a>
  834. </li>
  835. <li class="nav-item" data-depth="3">
  836. <a class="nav-link" href="../../sdk/terrain_editor.html">Terrain Editor</a>
  837. </li>
  838. <li class="nav-item" data-depth="3">
  839. <a class="nav-link" href="../../sdk/sample_code.html">Sample Code</a>
  840. </li>
  841. <li class="nav-item" data-depth="3">
  842. <a class="nav-link" href="../../sdk/material_editing.html">Material Editing</a>
  843. </li>
  844. <li class="nav-item" data-depth="3">
  845. <a class="nav-link" href="../../sdk/font_creation.html">Creating Bitmap Fonts</a>
  846. </li>
  847. <li class="nav-item" data-depth="3">
  848. <button class="nav-item-toggle"></button>
  849. <a class="nav-link" href="https://hub.jmonkeyengine.org/t/effecttrack-and-audiotrack-editing-in-the-sdk/23378">Audio and Effect Track Editing</a>
  850. <ul class="nav-list">
  851. <li class="nav-item" data-depth="4">
  852. <a class="nav-link" href="https://www.youtube.com/watch?v=D7JM4VMKqPc">Video: Effect and AudioTrack editing in jMonkeyEngine 3 sdk</a>
  853. </li>
  854. </ul>
  855. </li>
  856. <li class="nav-item" data-depth="3">
  857. <a class="nav-link" href="../../sdk/filters.html">Post-Processor Filter Editor and Viewer</a>
  858. </li>
  859. <li class="nav-item" data-depth="3">
  860. <a class="nav-link" href="../../core/app/state/application_states.html">Application States</a>
  861. </li>
  862. <li class="nav-item" data-depth="3">
  863. <a class="nav-link" href="../../core/scene/control/custom_controls.html">Custom Controls</a>
  864. </li>
  865. <li class="nav-item" data-depth="3">
  866. <a class="nav-link" href="../../sdk/vehicle_creator.html">Vehicle Creator</a>
  867. </li>
  868. </ul>
  869. </li>
  870. <li class="nav-item" data-depth="2">
  871. <button class="nav-item-toggle"></button>
  872. <span class="nav-text">Advanced Usage</span>
  873. <ul class="nav-list">
  874. <li class="nav-item" data-depth="3">
  875. <a class="nav-link" href="../../sdk/build_platform.html">Building jMonkeyEngine SDK</a>
  876. </li>
  877. <li class="nav-item" data-depth="3">
  878. <a class="nav-link" href="../../sdk/use_own_jme.html#.adoc">Using your own (modified) version of jME3 in jMonkeyEngine SDK</a>
  879. </li>
  880. <li class="nav-item" data-depth="3">
  881. <a class="nav-link" href="../../sdk/increasing_heap_memory.html">Increasing Heap Memory</a>
  882. </li>
  883. <li class="nav-item" data-depth="3">
  884. <a class="nav-link" href="../../sdk/log_files.html">Log Files</a>
  885. </li>
  886. </ul>
  887. </li>
  888. <li class="nav-item" data-depth="2">
  889. <button class="nav-item-toggle"></button>
  890. <span class="nav-text">Available external plugins</span>
  891. <ul class="nav-list">
  892. <li class="nav-item" data-depth="3">
  893. <a class="nav-link" href="../contributions.html">Contributions</a>
  894. </li>
  895. <li class="nav-item" data-depth="3">
  896. <a class="nav-link" href="../../sdk/neotexture.html">Neo Texture Editor for procedural textures</a>
  897. </li>
  898. <li class="nav-item" data-depth="3">
  899. <a class="nav-link" href="http://www.youtube.com/watch?v=yS9a9o4WzL8">Video: Mesh Tool &amp; Physics Editor</a>
  900. </li>
  901. </ul>
  902. </li>
  903. <li class="nav-item" data-depth="2">
  904. <button class="nav-item-toggle"></button>
  905. <a class="nav-link" href="../../sdk/development.html">Developing plugins for jMonkeyEngine SDK</a>
  906. <ul class="nav-list">
  907. <li class="nav-item" data-depth="3">
  908. <a class="nav-link" href="../../sdk/development/setup.html">Creating a plugin</a>
  909. </li>
  910. <li class="nav-item" data-depth="3">
  911. <a class="nav-link" href="../../sdk/development/general.html">Creating components</a>
  912. </li>
  913. <li class="nav-item" data-depth="3">
  914. <a class="nav-link" href="../../sdk/development/scene.html">The Main Scene</a>
  915. </li>
  916. <li class="nav-item" data-depth="3">
  917. <a class="nav-link" href="../../sdk/development/sceneexplorer.html">The Scene Explorer</a>
  918. </li>
  919. <li class="nav-item" data-depth="3">
  920. <a class="nav-link" href="../../sdk/development/projects_assets.html">Projects and Assets</a>
  921. </li>
  922. <li class="nav-item" data-depth="3">
  923. <a class="nav-link" href="../../sdk/development/extension_library.html">Create a library plugin from a jar file</a>
  924. </li>
  925. <li class="nav-item" data-depth="3">
  926. <a class="nav-link" href="../../sdk/development/model_loader.html">Create a new or custom model filetype and loader</a>
  927. </li>
  928. </ul>
  929. </li>
  930. </ul>
  931. </li>
  932. </ul>
  933. </li>
  934. </ul>
  935. </nav>
  936. </div>
  937. <div class="nav-panel-explore" data-panel="explore">
  938. <div class="context">
  939. <span class="title">JME</span>
  940. <span class="version">3.4</span>
  941. </div>
  942. <ul class="components">
  943. <li class="component is-current">
  944. <span class="title">JME</span>
  945. <ul class="versions">
  946. <li class="version">
  947. <a href="../../../3.8/documentation.html">3.8</a>
  948. </li>
  949. <li class="version is-current">
  950. <a href="../../documentation.html">3.4</a>
  951. </li>
  952. <li class="version">
  953. <a href="../../../3.3/documentation.html">3.3</a>
  954. </li>
  955. <li class="version">
  956. <a href="../../../3.2/documentation.html">3.2</a>
  957. </li>
  958. </ul>
  959. </li>
  960. <li class="component">
  961. <span class="title">Wiki Contribution</span>
  962. <ul class="versions">
  963. <li class="version">
  964. <a href="../../../../docs-wiki/3.8/wiki_contributor.html">3.8</a>
  965. </li>
  966. </ul>
  967. </li>
  968. <li class="component">
  969. <span class="title">Wiki UI</span>
  970. <ul class="versions">
  971. <li class="version">
  972. <a href="../../../../wiki-ui/index.html">master</a>
  973. </li>
  974. </ul>
  975. </li>
  976. </ul>
  977. </div>
  978. </div>
  979. </aside>
  980. </div>
  981. <main class="article">
  982. <div class="toolbar" role="navigation">
  983. <button class="nav-toggle"></button>
  984. <nav class="breadcrumbs" aria-label="breadcrumbs">
  985. <ul>
  986. <li><a href="../../documentation.html">JME</a></li>
  987. <li>User Contributions</li>
  988. <li>Tools</li>
  989. <li><a href="charts.html">Visualizing Maps in JME3 (Marine Charts)</a></li>
  990. </ul>
  991. </nav>
  992. <div class="page-versions">
  993. <button class="version-menu-toggle" title="Show other versions of page">3.4</button>
  994. <div class="version-menu">
  995. <a class="version" href="../../../3.8/contributions/tools/charts.html">3.8</a>
  996. <a class="version is-current" href="charts.html">3.4</a>
  997. <a class="version" href="../../../3.3/contributions/tools/charts.html">3.3</a>
  998. <a class="version" href="../../../3.2/contributions/tools/charts.html">3.2</a>
  999. </div>
  1000. </div>
  1001. <div class="edit-this-page"><a href="https://github.com/jMonkeyEngine/wiki/edit/v3.4/docs/modules/contributions/pages/tools/charts.adoc">Edit this Page</a></div>
  1002. </div>
  1003. <div class="content">
  1004. <article class="doc">
  1005. <h1 class="page">JME 3 Tutorial - Visualizing 3D Charts</h1>
  1006. <div id="preamble">
  1007. <div class="sectionbody">
  1008. <div class="paragraph">
  1009. <p>Previous: <a href="navigation.html" class="xref page">Navigation</a></p>
  1010. </div>
  1011. <div class="paragraph">
  1012. <p>In this tutorial we will have a look at creating a simple 3D cartography application that allows you to display 3D charts at different zoom levels.</p>
  1013. </div>
  1014. <div class="paragraph">
  1015. <p>This tutorial assumes that you know:</p>
  1016. </div>
  1017. <div class="ulist">
  1018. <ul>
  1019. <li>
  1020. <p>About the <a href="navigation.html" class="xref page">Navigation package</a>.</p>
  1021. </li>
  1022. <li>
  1023. <p>How to create a <a href="../../tutorials/beginner/hello_terrain.html" class="xref page">3D landscape</a> using image-based heightmaps.</p>
  1024. </li>
  1025. </ul>
  1026. </div>
  1027. <div class="paragraph">
  1028. <p><span class="image"><img src="../_images/tools/mercator_grid_3d_small.png" alt="mercator_grid_3d_small.png" width="" height=""></span></p>
  1029. </div>
  1030. <div class="paragraph">
  1031. <p>You will learn that how to account for distortions that arise when mapping of one coordinate system into (i.e. when converting longitude/latitude into JME&#8217;s World Units), how to construct a tile tree and how to render a dynamic mercator grid.</p>
  1032. </div>
  1033. <div class="paragraph">
  1034. <p><strong>This article was sponsored by <a href="http://planetmayo.com/">PlanetMayo Ltd</a></strong></p>
  1035. </div>
  1036. </div>
  1037. </div>
  1038. <div class="sect1">
  1039. <h2 id="displaying-your-first-chart"><a class="anchor" href="#displaying-your-first-chart"></a>Displaying your first chart</h2>
  1040. <div class="sectionbody">
  1041. <div class="paragraph">
  1042. <p>Let&#8217;s think about how we are going to get JME to display our terrain. The easiest way is to use JME&#8217;s`ImageBasedHeightMap`. Recall from the <a href="../../tutorials/beginner/hello_terrain.html" class="xref page">Hello Terrain</a> tutorial that these are grayscale images which JME uses to create a terrain quad. So, in order to display a chart, we need an image of a (two-dimensional) mercator projection (such as the one depicted below), which we then load using:</p>
  1043. </div>
  1044. <div class="listingblock">
  1045. <div class="content">
  1046. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Texture heightMapImage = assetManager.loadTexture(DEFAULT_HEIGHTMAP);
  1047. heightmap = new ImageBasedHeightMap(heightMapImage.getImage());
  1048. heightmap.load();
  1049. terrain = new TerrainQuad("terrain", 257, TERRAIN_SIZE, heightmap.getHeightMap());
  1050. applyDefaultTexture();</code></pre>
  1051. </div>
  1052. </div>
  1053. <div class="paragraph">
  1054. <p><span class="image"><img src="../_images/tools/globe.png" alt="A 256x256 mercator projection of planet earth." width="" height=""></span></p>
  1055. </div>
  1056. <div class="paragraph">
  1057. <p>In essence, 3D chart visualization is achieved by converting the polygons composing planet earth&#8217;s landmass into float matrices whereby each value within the matrix represents a specific terrain height. For example, given a terrain of 100 x 100 world units, we construct a heightmap by creating a 100 x 100 matrix. Each cell within the matrix corresponds to a terrain coordinate; each cell’s value to that coordinate’s desired height. But you already knew that, so where&#8217;s the tricky part? Well, when visualizing a chart an accurate projection requires a translation of latitude/longitude coordinates into their equivalent world unit (x,y,z) counterparts. This translation however is not a straight forward mapping of one coordinate system into the other due to the distortion arising from projecting an oblate spheroid onto a flat surface (see my previous wiki article <a href="navigation.html" class="xref page">here</a>). This means that if one would adhere to a linear scale, the Mercator projection would distort the size and shape of objects as the object distances itself from the equator, eventually resulting in infinite scaling as the pole is reached. So the first task at hand, is to construct accurate 2D projections of planet earth which we can then use as heightmaps. We can achieve this using the jme3.tools.navigation package and co-ordinate sets available at <a href="https://maps.ngdc.noaa.gov/viewers/geophysics/">noaa.gov</a>.</p>
  1058. </div>
  1059. <div class="paragraph">
  1060. <p>As <a href="navigation.html" class="xref page">previously discussed</a>, the distortion in latitude is derived by using the difference in meridional parts between the chart’s centre and the current position as a baseline; through converting the difference to world units by dividing it by the number of world units contained within one minute, a latitude’s y-coordinate can be obtained. Calculating a position’s x-coordinate is somewhat easier as the distortion only applies to latitude, not longitude. Therefore x merely equals the sum or difference between itself and the viewport’s centre coordinate, depending on the relative location of the position itself and the chart’s centre. Despite being able to convert between the two coordinate systems, slight precision problems remain once the chart projection is scaled down past a level of 6 meters. This is caused by the pixel referencing system of modern displays being integer based; once the ratio of minutes to pixels exceeds the aforementioned threshold, slight inaccuracies are introduced into the display. However this is of little relevance to most GIS (such as Debrief) as a) the inaccuracies are a matter of meters (or even centimetres) and b) it is impossible to notice this variation as GPS exposes a much higher inaccuracy (between 10 - 100 meters).</p>
  1061. </div>
  1062. <div class="admonitionblock tip">
  1063. <table>
  1064. <tr>
  1065. <td class="icon">
  1066. <i class="fa icon-tip" title="Tip"></i>
  1067. </td>
  1068. <td class="content">
  1069. <div class="paragraph">
  1070. <p>To lessen the computational load, coordinate system conversion should only takes place when either the chart is re-centered or a change in scale / resolution is requested. Once converted, the coordinate sets are rendered to a buffer whose contents is then drawn for every UI update cycle.</p>
  1071. </div>
  1072. </td>
  1073. </tr>
  1074. </table>
  1075. </div>
  1076. <div class="paragraph">
  1077. <p>.</p>
  1078. </div>
  1079. </div>
  1080. </div>
  1081. <div class="sect1">
  1082. <h2 id="creating-your-heightmaps"><a class="anchor" href="#creating-your-heightmaps"></a>Creating your heightmaps</h2>
  1083. <div class="sectionbody">
  1084. <div class="paragraph">
  1085. <p>There are two ways to create your heightmaps (also referred to as 'tiles' as each heightmap is a tile that composes our chart of the world). One is to use third-party software such as <a href="http://geotools.org/">GeoTools</a>. The other is to use the jme3.tools.navigation package to write a tile generator:</p>
  1086. </div>
  1087. <div class="listingblock">
  1088. <div class="content">
  1089. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class TileGenerator {
  1090. private int lineCount;
  1091. /* List of polygons representing the countries that are to be drawn. */
  1092. private List&lt;PositionContainer&gt; polygons;
  1093. /* The map projection used to generate the chart image. */
  1094. private MapModel2D map;
  1095. /* The chart's resolution in minutes of longitude per pixel. */
  1096. private double mpp;
  1097. /* The chart's centre. */
  1098. private Position centre;
  1099. /**
  1100. * Constructs a new instance of TileGenerator.
  1101. *
  1102. * @param worldSize The width of the chart for which tiles are to be
  1103. * generated.
  1104. * @since 1.0
  1105. */
  1106. public TileGenerator(int worldSize, double mpp, Position centre) {
  1107. File dataDirectory = new File("data");
  1108. map = new MapModel2D(worldSize);
  1109. lineCount = 0;
  1110. File[] files = dataDirectory.listFiles(new FileFilter() {
  1111. public boolean accept(File pathname) {
  1112. if (pathname.toString().endsWith(".out")) {
  1113. return true;
  1114. }
  1115. return false;
  1116. }
  1117. });
  1118. loadChartData(files);
  1119. this.mpp = mpp;
  1120. this.centre = centre;
  1121. }
  1122. public void createImageMap(int worldSize) {
  1123. map.setCentre(centre);
  1124. map.calculateMinutesPerPixel(mpp);
  1125. System.out.println("Generating chart with world width (in pixels): " + worldSize);
  1126. System.out.println("Generating chart with meters per pixel: " + map.getMetersPerPixel());
  1127. BufferedImage img = new BufferedImage(worldSize,
  1128. worldSize, BufferedImage.TYPE_BYTE_GRAY);
  1129. Graphics2D g = img.createGraphics();
  1130. Point point1, point2;
  1131. GeneralPath polygonPath;
  1132. g.setColor(Color.WHITE);
  1133. int containerSize;
  1134. for (PositionContainer container : polygons) {
  1135. polygonPath = new GeneralPath();
  1136. containerSize = container.getPositions().size();
  1137. for (int i = 1; i &lt; containerSize; i++) {
  1138. point1 = map.toPixel(container.getPositions().get(i));
  1139. point2 = map.toPixel(container.getPositions().get(i - 1));
  1140. polygonPath.moveTo((double) point1.getX(), (double) point1.getY());
  1141. polygonPath.lineTo((double) point1.getX(), (double) point1.getY());
  1142. polygonPath.lineTo((double) point2.getX(), (double) point2.getY());
  1143. }
  1144. g.draw(polygonPath);
  1145. }
  1146. // Write resulting image to file
  1147. try {
  1148. ImageIO.write(img, "png", new File("map.png"));
  1149. } catch (IOException ioe) {
  1150. ioe.printStackTrace();
  1151. }
  1152. }
  1153. /**
  1154. * Draws depth contours.
  1155. *
  1156. * @param img The image to draw to.
  1157. * @param worldSize The size of the chart.
  1158. * @since 1.0
  1159. */
  1160. private void drawContours(BufferedImage img, int worldSize) {
  1161. map.setCentre(centre);
  1162. map.calculateMinutesPerPixel(mpp);
  1163. BufferedImage img2 = new BufferedImage(worldSize,
  1164. worldSize, BufferedImage.TYPE_BYTE_GRAY);
  1165. Graphics2D g = img2.createGraphics();
  1166. g.drawImage(img, null, null);
  1167. Point point1, point2;
  1168. GeneralPath polygonPath;
  1169. // g.setColor(new Color(21, 21, 21));
  1170. g.setColor(Color.WHITE);
  1171. int containerSize;
  1172. for (PositionContainer container : polygons) {
  1173. polygonPath = new GeneralPath();
  1174. containerSize = container.getPositions().size();
  1175. for (int i = 1; i &lt; containerSize; i++) {
  1176. point1 = map.toPixel(container.getPositions().get(i));
  1177. point2 = map.toPixel(container.getPositions().get(i - 1));
  1178. polygonPath.moveTo((double) point1.getX(), (double) point1.getY());
  1179. polygonPath.lineTo((double) point1.getX(), (double) point1.getY());
  1180. polygonPath.lineTo((double) point2.getX(), (double) point2.getY());
  1181. }
  1182. g.draw(polygonPath);
  1183. }
  1184. // Write resulting image to file
  1185. try {
  1186. ImageIO.write(img2, "png", new File("map.png"));
  1187. } catch (IOException ioe) {
  1188. ioe.printStackTrace();
  1189. }
  1190. }
  1191. /**
  1192. * Loads country border information from .out files, parses the information
  1193. * and stores it as a PositionContainer which is later used to
  1194. * produce the .png chart image.
  1195. *
  1196. * @param files A List of files that contain
  1197. * country border data.
  1198. * @since 1.0
  1199. */
  1200. private void loadChartData(File[] files) {
  1201. Scanner scan;
  1202. PositionContainer countryBorderPosition;
  1203. polygons = new ArrayList&lt;PositionContainer&gt;(300);
  1204. String tmp = "";
  1205. String tmpLat;
  1206. String tmpLong;
  1207. StringTokenizer stk;
  1208. Position pos;
  1209. for (File file : files) {
  1210. try {
  1211. scan = new Scanner(file);
  1212. countryBorderPosition = new PositionContainer();
  1213. while (scan.hasNext()) {
  1214. tmp = scan.nextLine();
  1215. if (tmp.startsWith("{") || tmp.startsWith("$") || tmp.startsWith(";")) {
  1216. continue;
  1217. }
  1218. if (tmp.equals("-1")) {
  1219. polygons.add(countryBorderPosition);
  1220. countryBorderPosition = new PositionContainer();
  1221. continue;
  1222. }
  1223. stk = new StringTokenizer(tmp, " +");
  1224. while (stk.hasMoreTokens()) {
  1225. tmpLat = stk.nextToken().trim();
  1226. if (tmpLat.equals("-1")) {
  1227. polygons.add(countryBorderPosition);
  1228. countryBorderPosition = new PositionContainer();
  1229. continue;
  1230. }
  1231. tmpLong = stk.nextToken().trim();
  1232. pos = new Position(Double.parseDouble(tmpLat), Double.parseDouble(tmpLong));
  1233. countryBorderPosition.add(pos);
  1234. lineCount++;
  1235. }
  1236. }
  1237. } catch (Exception e) {
  1238. e.printStackTrace();
  1239. System.err.println(tmp);
  1240. }
  1241. }
  1242. }
  1243. public static void main(String[] args) {
  1244. System.out.println("Debug 3D Tile Generator");
  1245. System.out.println("===========================");
  1246. args = new String[3];
  1247. args[0] = "1.2";
  1248. args[1] = "51.8";
  1249. args[2] = "-8.3";
  1250. if (args.length &lt; 3 || args.length &gt; 3) {
  1251. System.err.println("Incorrect argument usage. Should be mpp latitude longitude");
  1252. System.err.println("Exiting");
  1253. return;
  1254. }
  1255. String mppStr = args[0];
  1256. String latitudeStr = args[1];
  1257. String longitudeStr = args[2];
  1258. double lon, lat, mpp;
  1259. Position centre;
  1260. try {
  1261. mpp = Double.parseDouble(mppStr);
  1262. } catch (Exception e) {
  1263. System.err.println("MPP must be of type Double or Integer.");
  1264. System.err.println("Exiting");
  1265. return;
  1266. }
  1267. try {
  1268. lat = Double.parseDouble(latitudeStr);
  1269. } catch (Exception e) {
  1270. System.err.println("Latitude must be of type Double or Integer.");
  1271. System.err.println("Exiting");
  1272. return;
  1273. }
  1274. try {
  1275. lon = Double.parseDouble(longitudeStr);
  1276. } catch (Exception e) {
  1277. System.err.println("Longitude must be of type Double or Integer.");
  1278. System.err.println("Exiting");
  1279. return;
  1280. }
  1281. try {
  1282. centre = new Position(lat, lon);
  1283. } catch (InvalidPositionException ipe) {
  1284. System.err.println("Invalid latitude or longitude coordinates.");
  1285. System.err.println("Exiting");
  1286. return;
  1287. }
  1288. System.out.println("Generating chart...Please wait...");
  1289. TileGenerator generator = new TileGenerator(TerrainViewer.TERRAIN_SIZE - 1, mpp, centre);
  1290. File chart = new File("map.png");
  1291. if (!chart.exists()) {
  1292. generator.createImageMap(TerrainViewer.TERRAIN_SIZE - 1);
  1293. }
  1294. try {
  1295. BufferedImage img = ImageIO.read(chart);
  1296. generator.drawContours(img, TerrainViewer.TERRAIN_SIZE - 1);
  1297. } catch (Exception e) {
  1298. e.printStackTrace();
  1299. }
  1300. System.out.println("Chart generated. Placed in file 'chart.png'. Exiting.");
  1301. }
  1302. }</code></pre>
  1303. </div>
  1304. </div>
  1305. <div class="paragraph">
  1306. <p>…where .out file contains longitude / latitude coordinate pairs defining landmass contours. Here an extract:</p>
  1307. </div>
  1308. <div class="listingblock">
  1309. <div class="content">
  1310. <pre class="highlightjs highlight"><code class="language-none hljs">51.79188150756147+-8.25435369629442
  1311. 51.79184641740534+-8.254357553715453
  1312. 51.79182071886024+-8.254353833180712
  1313. 51.79181370477922+-8.254312317813477
  1314. 51.79181369284153+-8.254267011113086
  1315. 51.79182535405747+-8.254221642581026
  1316. 51.79184870922772+-8.254183732747943
  1317. 51.79188146269924+-8.254183530764353
  1318. 51.79190724220316+-8.254221208836046
  1319. 51.79190960635914+-8.254296874457655
  1320. 51.79188150756147+-8.25435369629442
  1321. -1
  1322. 51.79165344300885+-8.255042583168985
  1323. 51.79161872648091+-8.255072177259352
  1324. 51.79158175153456+-8.255082912194254
  1325. 51.79156558301037+-8.255041382314799
  1326. 51.79156556852833+-8.254985072910559
  1327. 51.79158171385971+-8.254936452917438
  1328. 51.79159555664058+-8.25487274689492
  1329. 51.79161403682817+-8.254824070938184
  1330. 51.79164411466118+-8.254798004805433
  1331. 51.79168584436759+-8.254817161260844
  1332. 51.79170675060084+-8.25487006519348
  1333. 51.79169051462138+-8.254930145346941
  1334. 51.79167197282713+-8.254993914789209
  1335. 51.79165344300885+-8.255042583168985</code></pre>
  1336. </div>
  1337. </div>
  1338. <div class="paragraph">
  1339. <p>(-1 acts as a separator, denoting the end of one polygon and the beginning of another).</p>
  1340. </div>
  1341. <div class="paragraph">
  1342. <p>So what&#8217;s happening here? Well, we basically read the contents of all specified files, whereby each line is broken up into longitude/latitude pairs, converted into pixel (x,y) coordinates and used to construct a polygon which is added to a polygon container once a polygon separator is encountered. Once the object’s paint method is called, this polygon container is iterated and any polygons falling within the canvas (aka viewport) bounds are painted to the graphics context.
  1343. Essentially, this algorithm can be summarized as follows:</p>
  1344. </div>
  1345. <div class="listingblock">
  1346. <div class="content">
  1347. <pre class="highlightjs highlight"><code class="language-none hljs">Constructor ( files ):
  1348. for each file in files
  1349. for each line in file
  1350. if line == -1
  1351. polygonList.add(polygon)
  1352. new polygon
  1353. else
  1354. polygon.add(parse(line))
  1355. Paint ( graphics context ):
  1356. for each polygon in polygonList
  1357. if polygon inside view bounds
  1358. graphics context.paint(polygon)</code></pre>
  1359. </div>
  1360. </div>
  1361. <div class="paragraph">
  1362. <p><span class="image"><img src="../_images/tools/heightmap_modelling.png" alt="Summarizing process of visualizing a chart. From left to right: We draw the coordinates downloaded from noaa.gov. Ideally" width="" height=""></span>
  1363. <strong>Above:</strong> Summarizing process of visualizing a chart. From left to right: We draw the coordinates downloaded from noaa.gov. Ideally, each polygon should be filled in a light colour, whilst the surrounding ocean remains dark. JME uses these images to create an internal representation of the terrain (a float matrix).</p>
  1364. </div>
  1365. <div class="paragraph">
  1366. <p>The heightmaps produced by the <code>TileGenerator</code> are essentially arrays containing float values ranging from 0 to 255. For convenience and efficiency, JME treats these arrays as Portable Network Graphic (PNG) images (again, see the Hello Terrain tutorial). This allows us to store each tile as an image, meaning that each tile will only need to be constructed once. Essentially what the tile generator therefore does is draw a greyscale image of each tile whereby dark colours (i.e. low values from 0 - 50) are valleys and high values (200 - 255) become mountains or hills. In order to maintain scale, these values are scaled by dividing the seabed’s maximum height (in meters) by the meters per pixel of the current chart.
  1367. With only a few specified points, JME interpolates the rest, making terrain construction using heightmaps more efficient than defining individual vertices for each pixel on the chart.
  1368. A tile’s texture is defined by its ”Alphamap”. This is a copy of its heightmap, but instead of defining height values, the floats composing the alphamap image define textures. For this purpose, a method known as ”texture splatting” is employed, whereby texture data is colour coded. That is, assuming that a spatial has two texture layers (let’s call them Tex1 and Tex2), each layer is associated with a colour: in the case of Debrief 3D, blue refers to a sand texture and red refers to dirt/grass textures. Although such an approach to texturing may sound confusing at first, it has the advantages that both heightmaps and alphamaps can be created in one go, and, as they are based on the same principle, can easily be modified in batch rather than individually.</p>
  1369. </div>
  1370. </div>
  1371. </div>
  1372. <div class="sect1">
  1373. <h2 id="whats-all-this-talk-about-tiles"><a class="anchor" href="#whats-all-this-talk-about-tiles"></a>What&#8217;s all this talk about tiles?</h2>
  1374. <div class="sectionbody">
  1375. <div class="paragraph">
  1376. <p>A tile tree is our way of keeping track of individual tiles. All that it is, is a set of nested sub-directories that holds charts. The top-level directory (our root) contains a chart of the entire world, and each sub-directory an enlarged area of our planet. For example, inside the root, we may have folders that contain a chart just for Ireland, the UK and France. As we traverse the tree further, we get the individual counties or provinces for each country. One way for us to represent this mess of directories, is via a <a href="http://en.wikipedia.org/wiki/Search_tree">Search Tree</a>.</p>
  1377. </div>
  1378. </div>
  1379. </div>
  1380. <div class="sect1">
  1381. <h2 id="creating-a-tile-tree"><a class="anchor" href="#creating-a-tile-tree"></a>Creating a tile tree</h2>
  1382. <div class="sectionbody">
  1383. <div class="listingblock">
  1384. <div class="content">
  1385. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">try {
  1386. File resourceDirectory = new File(worldResourcesDirectory);
  1387. if (!resourceDirectory.isDirectory()) {
  1388. System.out.println("Resource path must be a directory");
  1389. System.exit(1);
  1390. }
  1391. worldStructure = new TileTree(resourceDirectory);
  1392. } catch (Exception e) {
  1393. e.printStackTrace();
  1394. }</code></pre>
  1395. </div>
  1396. </div>
  1397. <div class="paragraph">
  1398. <p>Upon initialization, these tiles are read into memory by the <code>TileTree</code> object which treats, as the name suggests, the tiles composing the chart as a tree whereby the root node refers to the entire globe. Its children refer to sub-sections of the globe, and its children in turn to sub-sections of that sub-section. For example, the ”Ireland” node is a direct child of the root node. The ”Cork Harbour” node in turn is a direct child of the ”Ireland” node and represents an enlarged version of a sub-section of the Irish coast. Each such Node consists of a unique ID (used to identify the node), a list of child nodes, a path to the heightmap (tile) that it represents, the zoom level (referred to as the longitude level as the zoom is defined by minutes of longitude per pixel) and a latitude/longitude pair denoting the tile’s centre.</p>
  1399. </div>
  1400. <div class="paragraph">
  1401. <p>Each heightmap is rendered depending on which ID the user selects (where each node in the tree is listed by its unique ID). As an ID is selected, the tree is traversed to find the node matching the given ID. The path to its heightmap is extracted and the heightmap is rendered by extracting the float array from the loaded image (that is, a texture object is created and loaded with the heightmap. A ImageBasedHeightMap object is then used to convert the heightmap and alphamap into corresponding height and texture arrays). → again, see JME tutorial on terrain.</p>
  1402. </div>
  1403. <div class="paragraph">
  1404. <p>The Tile Tree’s contents is stored in assets/Heightmaps, and each directory level is composed of one descriptor file, one heightmap (in the form of a PNG image) and one alphamap (also in the form of a PNG image). The descriptor files end in a.desc filename extension and contain the geo-coordinate centre of the tile as well as the resolution of the node that they are representing (as always, the resolution is represented in minutes per pixel (mpp)). A descriptor file’s sole purpose is to allow the re-construction of the tile tree upon application initialization. Specifically, this is achieved by the ChartModel object which instantiates the TileTree, passing a reference to <em>assets/Heightmaps</em>, which <code>TileTree</code> then recursively scans, constructing the tree by interpreting the descriptor files. It is worth noting that all files per level should be named according to the heightmap tile that it represents. That is, if your level represents a chart of Ireland and your heightmap is named Ireland.png then your descriptor file should be named <em>Ireland.desc</em>, while your alphamap should be named <em>Ireland.png.Alphamap.png</em>.</p>
  1405. </div>
  1406. <div class="paragraph">
  1407. <p><span class="image"><img src="../_images/tools/slide1.jpg" alt="The Tile Tree" width="" height=""></span>
  1408. <span class="image"><img src="../_images/tools/slide2.jpg" alt="Looking inside a node&#8230;&#8203;" width="" height=""></span>
  1409. <strong>Above:</strong> A look inside the &#8220;Ireland&#8221; node. We can see the heightmap, descriptor file and alphamap.</p>
  1410. </div>
  1411. <div class="listingblock">
  1412. <div class="content">
  1413. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">/*
  1414. * To change this template, choose Tools | Templates
  1415. * and open the template in the editor.
  1416. */
  1417. package util.datastructure;
  1418. import java.io.File;
  1419. import java.util.ArrayList;
  1420. import java.util.List;
  1421. import java.util.Scanner;
  1422. import jme3tools.navigation.Position;
  1423. /**
  1424. * The TileTree handles the storage and retrieval of individual
  1425. * charts. Each Node corresponds to one chart (a node's value being
  1426. * the chart's absolute path. It's ID being the ID under which it is displayed).
  1427. *
  1428. * The tree reflects the application's chart directory structure, with the world
  1429. * as its root and individual countries as its children. Sub-children of these nodes
  1430. * represent "close up" version of each country / geographic sub areas of those countries.
  1431. *
  1432. * @author Benjamin Jakobus
  1433. * @since 1.0
  1434. * @version 1.0
  1435. */
  1436. public class TileTree {
  1437. /* The tree's root node. */
  1438. private Node root;
  1439. /**
  1440. * Creates a new instance of TileTree. Nodes are generated
  1441. * depending on the contents of the resource directory.
  1442. *
  1443. * @param resourceDirectory The root of the application's resource
  1444. * directory (the resource directory being the
  1445. * directory in which all charts (aka Heightmaps)
  1446. * are being stored).
  1447. * @since 1.0
  1448. */
  1449. public TileTree(File resourceDirectory) {
  1450. File directory = null;
  1451. for (File f : resourceDirectory.listFiles()) {
  1452. if (f.isDirectory()) {
  1453. directory = f;
  1454. continue;
  1455. }
  1456. if (f.getName().endsWith(".desc")) {
  1457. root = initNode(f);
  1458. }
  1459. }
  1460. initTileTree(directory, root);
  1461. }
  1462. /**
  1463. * Initializes the tree's children. The root node should be initialized
  1464. * prior to calling this method.
  1465. *
  1466. * @param resourceDirectory The root of the application's resource
  1467. * directory (the resource directory being the
  1468. * directory in which all charts (aka Heightmaps)
  1469. * are being stored).
  1470. * @param parentNode The Node to which all
  1471. * subsequent nodes should be attached.
  1472. * @since 1.0
  1473. */
  1474. private void initTileTree(File resourceDirectory, Node parentNode) {
  1475. File directory = null;
  1476. Node node = null;
  1477. if (parentNode == null || resourceDirectory == null) {
  1478. return;
  1479. }
  1480. for (File f : resourceDirectory.listFiles()) {
  1481. if (f.isDirectory()) {
  1482. directory = f;
  1483. continue;
  1484. }
  1485. if (!f.getName().endsWith(".desc")) {
  1486. continue;
  1487. } else {
  1488. node = initNode(f);
  1489. }
  1490. }
  1491. parentNode.attachChild(node);
  1492. node = parentNode;
  1493. initTileTree(directory, parentNode);
  1494. }
  1495. /**
  1496. * Initializes an individual node depending on the contents of the descriptor
  1497. * file (for information on descriptor files, refer to the software documentation).
  1498. *
  1499. * @param file The descriptor File with
  1500. * which to initialize the node's contents.
  1501. * @return A new Node.
  1502. * @since 1.0
  1503. */
  1504. private Node initNode(File file) {
  1505. Node node = null;
  1506. Scanner scan;
  1507. String resourcePath = null;
  1508. String nodeID = null;
  1509. String longitudeLevel = null;
  1510. Position centre = null;
  1511. int currentLine = 0;
  1512. if (file == null) {
  1513. return node;
  1514. }
  1515. try {
  1516. scan = new Scanner(file);
  1517. resourcePath = file.getAbsolutePath().replace(".desc", ".png");
  1518. resourcePath = resourcePath.substring(resourcePath.indexOf("assets"));
  1519. nodeID = file.getName().replace(".desc", "") + "_" + file.getParentFile().getName();
  1520. while (scan.hasNextLine()) {
  1521. if (currentLine == 0) {
  1522. String tmp = scan.nextLine();
  1523. String[] array = tmp.split("\\+");
  1524. centre = new Position(Double.parseDouble(array[0]),
  1525. Double.parseDouble(array[1]));
  1526. currentLine++;
  1527. } else {
  1528. longitudeLevel = scan.nextLine().trim();
  1529. }
  1530. }
  1531. node = new Node(nodeID, resourcePath, longitudeLevel, centre);
  1532. } catch (Exception e) {
  1533. e.printStackTrace();
  1534. }
  1535. return node;
  1536. }
  1537. /**
  1538. * Returns the Node matching the given ID.
  1539. *
  1540. * @param nodeID The ID of the Node that you
  1541. * wish to retrieve.
  1542. * @return The Node matching the given ID.
  1543. * @since 1.0
  1544. */
  1545. public Node find(String nodeID) {
  1546. return find(root, nodeID);
  1547. }
  1548. /**
  1549. * Returns the Node matching the given ID. This method is similar
  1550. * to find() with the exception that it only begins searching from
  1551. * a certain node downwards.
  1552. *
  1553. * @param nodeToSearch The Node from which to start searching.
  1554. * @param nodeID The ID of the Node that you
  1555. * wish to retrieve.
  1556. * @return The Node matching the given ID.
  1557. * @since 1.0
  1558. */
  1559. private Node find(Node nodeToSearch, String nodeID) {
  1560. Node newNode = null;
  1561. if (nodeToSearch == null) {
  1562. return newNode;
  1563. }
  1564. if (nodeToSearch.getNodeID().trim().compareTo(nodeID.trim()) == 0) {
  1565. return nodeToSearch;
  1566. } else {
  1567. for (Node n : nodeToSearch.getChildren()) {
  1568. newNode = find(n, nodeID);
  1569. if (newNode != null) {
  1570. return newNode;
  1571. }
  1572. }
  1573. }
  1574. return newNode;
  1575. }
  1576. /**
  1577. * Retrieves all nodes within the tree.
  1578. *
  1579. * @return A List of all nodes within the
  1580. * tree.
  1581. * @since 1.0
  1582. */
  1583. public List&lt;Node&gt; getNodes() {
  1584. List&lt;Node&gt; nodes = new ArrayList&lt;Node&gt;();
  1585. getNodes(root, nodes);
  1586. return nodes;
  1587. }
  1588. /**
  1589. * Returns all the children of a specific Node.
  1590. *
  1591. * @param node The Node whose children you want.
  1592. * @param nodes The List to which to add these children.
  1593. * @since 1.0
  1594. */
  1595. private void getNodes(Node node, List&lt;Node&gt; nodes) {
  1596. if (node == null) {
  1597. return;
  1598. }
  1599. for (Node n : node.getChildren()) {
  1600. getNodes(n, nodes);
  1601. }
  1602. nodes.add(node);
  1603. }
  1604. }</code></pre>
  1605. </div>
  1606. </div>
  1607. <div class="listingblock">
  1608. <div class="title">.and the Node:</div>
  1609. <div class="content">
  1610. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">package util.datastructure;
  1611. import java.util.ArrayList;
  1612. import java.util.List;
  1613. import jme3tools.navigation.Position;
  1614. /**
  1615. * An individual node within the TileTree. Each Node
  1616. * represents an individual tile (i.e. heightmap + alphamap).
  1617. *
  1618. * @author Benjamin Jakobus
  1619. * @since 1.0
  1620. * @version 1.0
  1621. */
  1622. public class Node {
  1623. /* The node's unique identifier. */
  1624. private String nodeID;
  1625. /* Path to the resource that the node represents (aka the node's value). */
  1626. private String resource;
  1627. /* The node's children. */
  1628. private List&lt;Node&gt; children;
  1629. /* The resolution (width in degrees of longitude) represented by this node.
  1630. * i.e. the resolution of the chart that the node represents.
  1631. */
  1632. private double longitudeLevel;
  1633. /* The centre of the chart (aka tile) that the node represents. */
  1634. private Position centre;
  1635. /**
  1636. * Constructor.
  1637. *
  1638. * @param nodeID The node's unique identifier.
  1639. * @param resource Path to the resource that the node represents
  1640. * (aka the node's value).
  1641. * @param longitudeLevel The resolution (width in degrees of longitude)
  1642. * represented by this node.
  1643. * @param centre The centre of the chart (aka tile) that the
  1644. * node represents.
  1645. * @since 1.0
  1646. */
  1647. public Node(String nodeID, String resource, String longitudeLevel, Position centre) {
  1648. this.nodeID = nodeID;
  1649. this.resource = resource;
  1650. this.longitudeLevel = Double.parseDouble(longitudeLevel);
  1651. this.centre = centre;
  1652. children = new ArrayList&lt;Node&gt;();
  1653. }
  1654. /**
  1655. * Returns all of the node's children.
  1656. *
  1657. * @return A List containing all of the node's children.
  1658. * @since 1.0
  1659. */
  1660. public List&lt;Node&gt; getChildren() {
  1661. return children;
  1662. }
  1663. /**
  1664. * Returns the node's ID.
  1665. *
  1666. * @return The node's unique identifier.
  1667. * @since 1.0
  1668. */
  1669. public String getNodeID() {
  1670. return nodeID;
  1671. }
  1672. /**
  1673. * Returns the path to the tile that the node represents.
  1674. *
  1675. * @return The path to the tile that the node represents.
  1676. * @since 1.0
  1677. */
  1678. public String getResource() {
  1679. return resource;
  1680. }
  1681. /**
  1682. * Attaches a child to this node.
  1683. *
  1684. * @param child The Node to attach.
  1685. * @since 1.0
  1686. */
  1687. public void attachChild(Node child) {
  1688. children.add(child);
  1689. }
  1690. /**
  1691. * Returns the width in degrees of longitude of the chart / resource that this
  1692. * node represents.
  1693. *
  1694. * @return the width in degrees of longitude of the chart / resource
  1695. * that this node represents.
  1696. * @since 1.0
  1697. */
  1698. public double getLongitudeLevel() {
  1699. return longitudeLevel;
  1700. }
  1701. /**
  1702. * The centre coordinate of the tile / chart that this node represents.
  1703. *
  1704. * @return The chart's centre in terms of latitude / longitude.
  1705. * @since 1.0
  1706. */
  1707. public Position getCentre() {
  1708. return centre;
  1709. }
  1710. }</code></pre>
  1711. </div>
  1712. </div>
  1713. <div class="paragraph">
  1714. <p>Loading a new chart is simple: all that we need to do is get the TileTree to find the chart for us (it&#8217;ll handle loading the descriptor file and just return a node):</p>
  1715. </div>
  1716. <div class="listingblock">
  1717. <div class="content">
  1718. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Node node = tileTree.find(chartID);</code></pre>
  1719. </div>
  1720. </div>
  1721. <div class="paragraph">
  1722. <p>We then use the returned node, to adjust our zoom-level:</p>
  1723. </div>
  1724. <div class="listingblock">
  1725. <div class="content">
  1726. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">mapModel.calculateMinutesPerWorldUnit(node.getLongitudeLevel());
  1727. mapModel.setCentre(node.getCentre());</code></pre>
  1728. </div>
  1729. </div>
  1730. </div>
  1731. </div>
  1732. <div class="sect1">
  1733. <h2 id="drawing-the-mercator-grid"><a class="anchor" href="#drawing-the-mercator-grid"></a>Drawing the Mercator Grid</h2>
  1734. <div class="sectionbody">
  1735. <div class="paragraph">
  1736. <p>A mercator grid reflects the ”stretching” of the flat Mercator chart through the widening of the longitude / latitude lines. Using JME’s Mesh class, a 3D representation of the grid can be drawn procedurally (as opposed to pre-defining the mesh’s vertices using a 3D modelling tool such as Blender). This is achieved by defining a vector of positions, whereby each entry i within the vector denotes the starting point of a grid line, and i + 1 defining the line’s end-point. Next, the the order in which the mesh is constructed from these coordinates is defined. These are basically index pairs as the mesh consists of a set of lines, each having a start and end point. Finally, the coordinates vector and the indices are added to the mesh, which in turn is used to define the Geometry that is added to the scene graph:</p>
  1737. </div>
  1738. <div class="listingblock">
  1739. <div class="content">
  1740. <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public void createGrid(double longitudeLevel, float increment) {
  1741. granularity = increment;
  1742. Mesh m = new Mesh();
  1743. m.setMode(Mesh.Mode.Lines);
  1744. m.setLineWidth(1f);
  1745. float max = (longitudeLevel &lt; 8 ? 2 : 85);
  1746. float max2 = (longitudeLevel &lt; 8 ? 180 / 8 : 180);
  1747. Vector3f[] positions = new Vector3f[(int) (Math.ceil(max / increment) * 4) + (int) (Math.ceil(max2 / increment) * 4)];
  1748. Position pos;
  1749. int i = 0;
  1750. try {
  1751. // Calculate initial spacings for the meridians and
  1752. // parallels
  1753. // Approach the grid construction from north to south and
  1754. // east to west.
  1755. positions[0] = new Vector3f(0, 0, 0);
  1756. // Latitude lines for northern hemisphere
  1757. for (float lat = 0; lat &lt; max; lat += increment, i += 2) {
  1758. pos = new Position(lat, 180);
  1759. positions[i] = TerrainViewer.mapModel.toWorldUnit(new Position(lat, -180));
  1760. positions[i + 1] = TerrainViewer.mapModel.toWorldUnit(pos);
  1761. }
  1762. // Latitude lines for southern hemisphere
  1763. for (float lat = 0; lat &lt; max; lat += increment, i += 2) {
  1764. pos = new Position(lat * -1, 180);
  1765. positions[i] = TerrainViewer.mapModel.toWorldUnit(new Position(lat * -1, -180));
  1766. positions[i + 1] = TerrainViewer.mapModel.toWorldUnit(pos);
  1767. }
  1768. max = (longitudeLevel &lt; 8 ? 180 / 8 : 180);
  1769. // Longitude lines for northern hemisphere
  1770. for (float lon = 0; lon &lt; max; lon += increment, i += 2) {
  1771. pos = new Position(85, lon);
  1772. positions[i] = TerrainViewer.mapModel.toWorldUnit(new Position(-85, lon));
  1773. positions[i + 1] = TerrainViewer.mapModel.toWorldUnit(pos);
  1774. }
  1775. // Longitude lines for southern hemisphere
  1776. for (float lon = 0; lon &lt; max; lon += increment, i += 2) {
  1777. pos = new Position(85, lon * -1);
  1778. positions[i] = TerrainViewer.mapModel.toWorldUnit(new Position(-85, lon * -1));
  1779. positions[i + 1] = TerrainViewer.mapModel.toWorldUnit(pos);
  1780. }
  1781. } catch (Exception ipe) {
  1782. }
  1783. int[] indices = new int[i];
  1784. int v;
  1785. for (i = 0, v = 0; i &lt; indices.length; i += 2, v++) {
  1786. indices[i] = i;
  1787. indices[i + 1] = i + 1;
  1788. }
  1789. m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(positions));
  1790. m.setBuffer(Type.Index, 1, indices);
  1791. m.updateBound();
  1792. m.updateCounts();
  1793. Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
  1794. mat.setColor("m_Color", ColorRGBA.Gray);
  1795. gridGeometry = new Geometry("Grid", m);
  1796. gridGeometry.setMaterial(mat);
  1797. Vector3f worldCentre = TerrainViewer.mapModel.getCentreWu();
  1798. gridGeometry.setLocalTranslation(new Vector3f(worldCentre.getX(),
  1799. gridHeight, worldCentre.getZ()));
  1800. }</code></pre>
  1801. </div>
  1802. </div>
  1803. <div class="paragraph">
  1804. <p><span class="image"><img src="../_images/tools/screen_shot_2011-12-18_at_13.12.01.png" alt="screen_shot_2011-12-18_at_13.12.01.png" width="" height=""></span></p>
  1805. </div>
  1806. </div>
  1807. </div>
  1808. <nav class="pagination">
  1809. <span class="prev"><a href="navigation.html">Mercator Projection Tool (Marine Navigation)</a></span>
  1810. <span class="next"><a href="../projects/rise_of_mutants_project.html">Rise of Mutants Project</a></span>
  1811. </nav>
  1812. </article>
  1813. <aside class="toc sidebar" data-title="Contents" data-levels="2">
  1814. <div class="toc-menu"></div>
  1815. </aside>
  1816. </div>
  1817. </main>
  1818. </div>
  1819. <footer class="footer">
  1820. <p>Copyright 2020 jMonkeyEngine Wiki Contributors. Licensed BSD-3.</p>
  1821. </footer>
  1822. <script src="../../../../_/js/vendor/docsearch.min.js"></script>
  1823. <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js -->
  1824. <script>
  1825. var search = docsearch({
  1826. apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
  1827. indexName: 'jmonkeyengine',
  1828. inputSelector: '#search-input',
  1829. autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
  1830. algoliaOptions: { hitsPerPage: 10 }
  1831. }).autocomplete
  1832. search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
  1833. function focusSearchInput () { document.querySelector('#search-input').focus() }
  1834. if (document.querySelector('.home-link.is-current')) window.addEventListener('load', focusSearchInput)
  1835. </script>
  1836. <script src="../../../../_/js/site.js"></script>
  1837. <script async src="../../../../_/js/vendor/highlight.js"></script>
  1838. </body>
  1839. </html>