12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <title>jMonkeyEngine Artificial Intelligence :: jMonkeyEngine Docs</title>
- <link rel="canonical" href="https://wiki.jmonkeyengine.org/docs/3.8/contributions/ai/jme3_ai.html">
- <link rel="prev" href="steer_behaviours.html">
- <link rel="next" href="../gui/topic_contributions_gui.html">
- <meta name="generator" content="Antora 3.0.1">
- <link rel="stylesheet" href="../../../../_/css/site.css">
- <meta property="og:image" content="https://wiki.jmonkeyengine.org/_/img/iconx128.png">
- <meta property="og:description" content="jMonkeyEngine Artificial Intelligence">
- <meta property="og:title" content="jMonkeyEngine Docs">
- <link rel="stylesheet" href="../../../../_/css/site-extra.css">
- <link rel="stylesheet" href="../../../../_/css/vendor/docsearch.min.css">
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css -->
- <link rel="icon" href="../../../../_/img/favicon.ico" type="image/x-icon">
- </head>
- <body class="article">
- <header class="header">
- <nav class="navbar">
- <div class="navbar-brand">
- <a class="navbar-item" href="https://wiki.jmonkeyengine.org">
- <img alt="" src="../../../../_/img/jme-logo.png" height="32" type="image/x-icon">
- </a>
- <div class="navbar-item hide-for-print">
- <input id="search-input" type="text" placeholder="Search docs">
- </div>
- <button class="navbar-burger" data-target="topbar-nav">
- <span></span>
- <span></span>
- <span></span>
- </button>
- </div>
- <div id="topbar-nav" class="navbar-menu">
- <div class="navbar-end">
- <div class="navbar-item theme-switch-wrapper">
- <label class="theme-switch" for="checkbox">
- <input type="checkbox" id="checkbox" />
- <div class="slider round"></div>
- </label>
- </div>
- <a class="navbar-item" href="https://github.com/jmonkeyengine/wiki">Github</a>
- </div>
- </div>
- </nav>
- </header>
- <div class="body">
- <div class="nav-container" data-component="docs" data-version="3.4">
- <aside class="nav">
- <div class="panels">
- <div class="nav-panel-menu is-active" data-panel="menu">
- <nav class="nav-menu">
- <h3 class="title"><a href="../../documentation.html">JME</a></h3>
- <ul class="nav-list">
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../documentation.html">Getting Started</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="https://javadoc.jmonkeyengine.org/v3.4.1-stable">JavaDoc</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../release.html">Release Guide</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../tutorials/beginner/beginner.html">Beginner Tutorials</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_simpleapplication.html">Hello SimpleApplication</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_node.html">Hello Node</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_asset.html">Hello Asset</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_main_event_loop.html">Hello Update Loop</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_input_system.html">Hello Input System</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_material.html">Hello Material</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_animation.html">Hello Animation</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_picking.html">Hello Picking</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_collision.html">Hello Collision</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_terrain.html">Hello Terrain</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_audio.html">Hello Audio</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_effects.html">Hello Effects</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/beginner/hello_physics.html">Hello Physics</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Key Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/best_practices.html">Best Practices</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/optimization.html">Optimization</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/faq.html">Frequently Asked Questions</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/math_for_dummies.html">Math for Dummies</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/math.html">Math overview</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/math_cheet_sheet.html">3D math "cheat sheet"</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/rotate.html">3-D Rotation</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/math_video_tutorials.html">Math video tutorial series</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/multi-media_asset_pipeline.html">Multi-Media Asset Pipeline</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/the_scene_graph.html">The Scene Graph</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/scenegraph_for_dummies.html">Scene Graph for Dummies</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/terminology.html">3D Graphics Terminology</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/concepts/transparency_sorting.html">Transparency Sorting</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Articles and How-to’s</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">How to Model</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../tutorials/how-to/modeling/3dsmax/3dsmax.html">3dsmax</a>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender.html">Blender</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_buffer_clearing.html">Buffer Clearing</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_gltf.html">Export as GlTF</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_ogre_export.html">Export as Ogre XML</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/blender_ogre_compatibility.html">Ogre Compatibility</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/makehuman.html">MakeHuman</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/makehuman_blender_ogrexml_toolchain.html">MakeHuman toolchain</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">How to Animate</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Mixamo</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/modeling/blender/mixamo.html">Blender Models</a>
- </li>
- <li class="nav-item" data-depth="4">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Video</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="5">
- <a class="nav-link" href="https://youtu.be/jHgAgTWIers?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 1- Download Model</a>
- </li>
- <li class="nav-item" data-depth="5">
- <a class="nav-link" href="https://youtu.be/GQJSrOpNQwI?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 2- Rig and Animate</a>
- </li>
- <li class="nav-item" data-depth="5">
- <a class="nav-link" href="https://youtu.be/JzRe2Dxbcmc?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 3- Import to JME</a>
- </li>
- <li class="nav-item" data-depth="5">
- <a class="nav-link" href="https://youtu.be/8wwDRDJop7k?list=PLv6qR9TGkz8RcUr-fOHI2SksWA4BAU9TS">Part 4- Play Animation</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/how-to/debugging.html">Debugging with Wireframes</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../tutorials/how-to/util/free_skymaps.html">How to create free skymaps</a>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Java Tips</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../tutorials/how-to/java/localization.html">Localization</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../tutorials/how-to/java/swing_canvas.html">Swing Canvas</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../tutorials/how-to/java/logging.html">Logging</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../tutorials/how-to/java/read_graphic_card_capabilites.html">Read Graphics Capabilities</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Articles</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Physically Based Rendering</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part1.html">PBR – Part one</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part2.html">PBR – Part two</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../tutorials/how-to/articles/pbr/pbr_part3.html">PBR – Part three</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Core Engine</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/simpleapplication.html">SimpleApplication</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/system/appsettings.html">AppSettings</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Controlling Game Logic</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/update_loop.html">Update Loop</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/state/application_states.html">Application States</a>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../core/scene/control/custom_controls.html">Custom Controls</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Video</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="https://www.youtube.com/watch?v=MNDiZ9YHIpM">Control any scene node</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="https://www.youtube.com/watch?v=-OzRZscLlHY">Control a character</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="https://wiki.jmonkeyengine.org/Scenes/SDK-UsecaseDemo_1.zip">Video Source Code</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/multithreading.html">Multithreading</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Scene Graph</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/scene/traverse_scenegraph.html">Traverse SceneGraph</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/scene/spatial.html">Spatial: Node vs Geometry</a>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../core/scene/mesh.html">Mesh</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/scene/custom_meshes.html">Custom Meshes</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/scene/shape/shape.html">Shape</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/scene/3d_models.html">3D Models</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/asset/asset_manager.html">Asset Manager</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/export/save_and_load.html">Saving and Loading Nodes</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/collision/collision_and_intersection.html">Collision and Intersection</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/scene/control/level_of_detail.html">Level of Detail</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Animation, Scene</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/animation/animation.html">Animation-Old</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/cinematic/cinematics.html">Cinematics (cutscenes, fake destruction physics)</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/cinematic/motionpath.html">MotionPaths and Waypoints</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Material, Light, Shadow</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/material/how_to_use_materials.html">How to use Materials</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/material/j3m_material_files.html">.j3m Material Files</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/material/material_definitions.html">.j3md Material Definitions</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/material/materials_overview.html">.j3md Properties</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/shader/jme3_shaders.html">Shaders and JME3</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/shader/jme3_shadernodes.html">Shader Node System</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/shader/shader_video_tutorials.html">Shader Video Tutorials</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/light/light_and_shadow.html">Light and Shadow</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/texture/anisotropic_filtering.html">Anisotropic Filtering</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/system/jme3_srgbpipeline.html">Gamma Correction</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Audio, Video</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/audio/audio.html">Playing Sounds</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/audio/audio_environment_presets.html">Audio Environment Presets</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/state/screenshots.html">Capture Screenshots</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/app/state/capture_audio_video_to_a_file.html">Capture Audio/Video</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Filter, Effect</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/effect/effects_overview.html">Overview</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/effect/bloom_and_glow.html">Bloom and Glow</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/effect/particle_emitters.html">Particle Emitters</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Landscapes</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/util/sky.html">Sky</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/terrain/terrain.html">Terrain (TerraMonkey)</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/collision/terrain_collision.html">Terrain Collision</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/effect/water.html">Simple Water</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/effect/post-processor_water.html">Post-Processor Water</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Camera</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/renderer/camera.html">Camera</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/renderer/making_the_camera_follow_a_character.html">Follow a Character</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/renderer/remote-controlling_the_camera.html">Remote-Controlling</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/renderer/multiple_camera_views.html">Multiple Camera Views</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/renderer/jme3_renderbuckets.html">Render Buckets</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">User Interaction</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/input/input_handling.html">Input Handling</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/input/combo_moves.html">Combo Moves</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/input/mouse_picking.html">Mouse Picking</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../core/gui/topic_gui.html">Graphical User Interface</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Nifty GUI</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/gui/nifty_gui.html">Integration Tutorial</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/gui/nifty_gui_best_practices.html">Best Practices</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/gui/nifty_gui_scenarios.html">Scenarios</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/ui/hud.html">Head-Up Display (HUD)</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Virtual Reality</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/vr/virtualreality.html">Virtual Reality</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../core/vr/virtualrealitycontrollers.html">Virtual Reality Controllers</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../physics/physics.html">Physics</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/bullet_multithreading.html">Multi-Threaded Physics</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/collision/physics_listeners.html">Collision Detection</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/joint/hinges_and_joints.html">Hinges and Joints</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/control/walking_character.html">Walking Character</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/control/ragdoll.html">Ragdoll</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/control/vehicles.html">Vehicles</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/control/softbody.html">Softbody</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../physics/bullet_pitfalls.html">Bullet Physics Pitfalls</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Networking</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../networking/networking.html">Networking (SpiderMonkey)</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../networking/headless_server.html">Headless Server</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../networking/monkey_zone.html">Multi-Player Demo Code</a>
- </li>
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../../networking/networking_video_tutorials.html">Networking Video Tutorials</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">User Contributions</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <a class="nav-link" href="../contributions.html">User Made Utilities</a>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Shader</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../shader/shaderblow_project.html">ShaderBlow Project</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Landscapes</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../lanscapes/vegetationsystem/vegetationsystem.html">Vegetation System</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Networking</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../networking/open_game_finder.html">Open Game Finder</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Entity System</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="#es/entitysystem.adoc">The Zay-ES Entity System</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Artificial Intelligence</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="recast.html">Recast Navigation</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="building_recast.html">Updating and building Recast Native Bindings</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="monkey_brains.html">Monkey Brains</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="steer_behaviours.html">Steer Behaviours</a>
- </li>
- <li class="nav-item is-current-page" data-depth="3">
- <a class="nav-link" href="jme3_ai.html">jME3 Artificial Intelligence</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../gui/topic_contributions_gui.html">GUI</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../contributions.html#lemur-gui-library">Lemur - a native jME3 GUI library with scene graph tools</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../contributions.html#tonegodgui">tonegodGUI - a native jME3 GUI library</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../contributions.html#immediate-graphical-user-interface">Immediate graphical user interface</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Tools</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../tools/navigation.html">Mercator Projection Tool (Marine Navigation)</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../tools/charts.html">Visualizing Maps in JME3 (Marine Charts)</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Projects</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../projects/rise_of_mutants_project.html">Rise of Mutants Project</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../sdk/sdk.html">SDK</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Video Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">SDK Use Case Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=-OzRZscLlHY">Demo 1 (Quixote demo)</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=6-YWxD3JByE">Demo 2 (Models and Materials)</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">SDK Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=M1_0pbeyJzI">Basics</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=nL7woH40i5c">Importing Models</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=DUmgAjiNzhY">Dragging&Dropping Nodes</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=ntPAmtsQ6eM">Scene Composing</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=zgPV3W6dD4s">Terrain with Collision Shape</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=Feu3-mrpolc">Working with Materials</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=MNDiZ9YHIpM">Custom Controls</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=oZnssg8TBWQ">WebStart Deployment</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="http://www.youtube.com/watch?v=D7JM4VMKqPc">Animation and Effect TrackEditing</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Getting Started</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/update_center.html">Updating jMonkeyEngine SDK</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/troubleshooting.html">Troubleshooting</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Java Development Features</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/project_creation.html">Project Creation</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/code_editor.html">Code Editor and Palette</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/version_control.html">File Version Control</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/debugging_profiling_testing.html">Debug, Profile, Test</a>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../sdk/application_deployment.html">Application Deployment</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../sdk/default_build_script.html">Default Build Script</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../sdk/android.html">Android</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../sdk/android_cheat_sheet.html">Android Cheat Sheet</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../sdk/ios.html">iOS</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Unique Features</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../sdk/model_loader_and_viewer.html">Import, View, Convert Models</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../../sdk/asset_packs.html">Asset Packs</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/scene_explorer.html">The SceneExplorer</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/scene_composer.html">Composing a Scene</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/terrain_editor.html">Terrain Editor</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/sample_code.html">Sample Code</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/material_editing.html">Material Editing</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/font_creation.html">Creating Bitmap Fonts</a>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="https://hub.jmonkeyengine.org/t/effecttrack-and-audiotrack-editing-in-the-sdk/23378">Audio and Effect Track Editing</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="https://www.youtube.com/watch?v=D7JM4VMKqPc">Video: Effect and AudioTrack editing in jMonkeyEngine 3 sdk</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/filters.html">Post-Processor Filter Editor and Viewer</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/app/state/application_states.html">Application States</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../core/scene/control/custom_controls.html">Custom Controls</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/vehicle_creator.html">Vehicle Creator</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Advanced Usage</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/build_platform.html">Building jMonkeyEngine SDK</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/use_own_jme.html#.adoc">Using your own (modified) version of jME3 in jMonkeyEngine SDK</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/increasing_heap_memory.html">Increasing Heap Memory</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/log_files.html">Log Files</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Available external plugins</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../contributions.html">Contributions</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/neotexture.html">Neo Texture Editor for procedural textures</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="http://www.youtube.com/watch?v=yS9a9o4WzL8">Video: Mesh Tool & Physics Editor</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../sdk/development.html">Developing plugins for jMonkeyEngine SDK</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/setup.html">Creating a plugin</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/general.html">Creating components</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/scene.html">The Main Scene</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/sceneexplorer.html">The Scene Explorer</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/projects_assets.html">Projects and Assets</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/extension_library.html">Create a library plugin from a jar file</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../../sdk/development/model_loader.html">Create a new or custom model filetype and loader</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </nav>
- </div>
- <div class="nav-panel-explore" data-panel="explore">
- <div class="context">
- <span class="title">JME</span>
- <span class="version">3.4</span>
- </div>
- <ul class="components">
- <li class="component is-current">
- <span class="title">JME</span>
- <ul class="versions">
- <li class="version">
- <a href="../../../3.8/documentation.html">3.8</a>
- </li>
- <li class="version is-current">
- <a href="../../documentation.html">3.4</a>
- </li>
- <li class="version">
- <a href="../../../3.3/documentation.html">3.3</a>
- </li>
- <li class="version">
- <a href="../../../3.2/documentation.html">3.2</a>
- </li>
- </ul>
- </li>
- <li class="component">
- <span class="title">Wiki Contribution</span>
- <ul class="versions">
- <li class="version">
- <a href="../../../../docs-wiki/3.8/wiki_contributor.html">3.8</a>
- </li>
- </ul>
- </li>
- <li class="component">
- <span class="title">Wiki UI</span>
- <ul class="versions">
- <li class="version">
- <a href="../../../../wiki-ui/index.html">master</a>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- </aside>
- </div>
- <main class="article">
- <div class="toolbar" role="navigation">
- <button class="nav-toggle"></button>
- <nav class="breadcrumbs" aria-label="breadcrumbs">
- <ul>
- <li><a href="../../documentation.html">JME</a></li>
- <li>User Contributions</li>
- <li>Artificial Intelligence</li>
- <li><a href="jme3_ai.html">jME3 Artificial Intelligence</a></li>
- </ul>
- </nav>
- <div class="page-versions">
- <button class="version-menu-toggle" title="Show other versions of page">3.4</button>
- <div class="version-menu">
- <a class="version" href="../../../3.8/contributions/ai/jme3_ai.html">3.8</a>
- <a class="version is-current" href="jme3_ai.html">3.4</a>
- <a class="version" href="../../../3.3/contributions/ai/jme3_ai.html">3.3</a>
- <a class="version" href="../../../3.2/contributions/ai/jme3_ai.html">3.2</a>
- </div>
- </div>
- <div class="edit-this-page"><a href="https://github.com/jMonkeyEngine/wiki/edit/v3.4/docs/modules/contributions/pages/ai/jme3_ai.adoc">Edit this Page</a></div>
- </div>
- <div class="content">
- <article class="doc">
- <h1 class="page">jMonkeyEngine Artificial Intelligence</h1>
- <div id="preamble">
- <div class="sectionbody">
- <div class="paragraph">
- <p>Most games written need some type of <a href="https://en.wikipedia.org/wiki/Artificial_intelligence_(video_games)">Artificial Intelligence</a> to deliver a feeling of realism, excitement or challenge to the player. AI can be as simple as having an NPC (Non Player Character) respond to some action taken by a player or as complicated as smoothly navigating your way through a scene full of obstacles without getting stuck. It’s a time-consuming and significant challenge to develop these systems so its much easier to use an existing library to do the heavy lifting for you.</p>
- </div>
- <div class="paragraph">
- <p>Unfortunately, the jMonkeyEngine comes with no official library for dealing with AI. There is, however, the jme3 Artificial Intelligence library that is probably the closest there is to an official release. Although it never made it into any official releases, it was designed, in part, by core team members. It consists of two separate AI models, a <a href="https://en.wikipedia.org/wiki/Navigation_mesh">Navigation Mesh</a> library using <a href="https://en.wikipedia.org/wiki/Pathfinding">path-finding</a>, and a simple Steering Behaviours library that uses path-following.</p>
- </div>
- <div class="paragraph">
- <p>You can read about the introduction of the library in the forum thread: <a href="https://hub.jmonkeyengine.org/t/ai-plugin-now-with-navmesh-pathfinding/24644">AI plugin now with NavMesh path-finding</a>.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="requirements"><a class="anchor" href="#requirements"></a>Requirements</h2>
- <div class="sectionbody">
- <div class="ulist">
- <ul>
- <li>
- <p><a href="https://github.com/MeFisto94/jme3-artificial-intelligence/releases">jme3 Artificial Intelligence Library</a> - The library and javaDocs for jme3AI. This is also where you can report problems or help in maintaining the library.</p>
- </li>
- <li>
- <p><a href="https://github.com/stevefsp/critterai/releases">CritterAI</a> - Stephen Pratt’s <a href="http://www.critterai.org/projects/nmgen_study/">NMGen Study</a> project files to generate the navmesh.</p>
- </li>
- <li>
- <p>To get the assets (3D models) used in this example, add the <a href="../../sdk/sample_code.html#jme3testdata-assets" class="xref page">jME3-testdata.jar</a> to your classpath.</p>
- </li>
- <li>
- <p>Java SDK 8+.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Stephen Pratt explains in detail the configuration parameters of CritterAI/Jme3AI in a easy to follow format and is suggested reading.</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p><a href="http://www.critterai.org/projects/nmgen_study/config.html">Configuration Parameters</a></p>
- </li>
- </ul>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="use-example"><a class="anchor" href="#use-example"></a>Use Example</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>The jme3 Artificial Intelligence Library contains:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>NavMesh - A Navigation Mesh path-finding AI system using the <a href="https://en.wikipedia.org/wiki/A*_search_algorithm">A*</a> algorithm.<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
- </li>
- <li>
- <p>Steering - The foundations of an <a href="http://natureofcode.com/book/chapter-6-autonomous-agents/">Autonomous Agent</a> system that uses path-following and forces to move a character through its environment. Includes a test case as well.<sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup></p>
- </li>
- </ul>
- </div>
- <div class="admonitionblock note">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-note" title="Note"></i>
- </td>
- <td class="content">
- <div class="paragraph">
- <p>This scope of this tutorial is restricted to the NavMesh part of the library and expands upon the lessons taught in the <a href="../../tutorials/beginner/beginner.html" class="xref page">tutorials</a>. It demonstrates the use of some classes and methods found in the Medium and Advanced topics of the wiki as well. You can find the source code for this tutorial in the <a href="https://github.com/jMonkeyEngine/doc-examples/tree/master/src/com/jme3/examples/jme3ai">jMonkeyEngine/docs-examples</a> repository.</p>
- </div>
- </td>
- </tr>
- </table>
- </div>
- <div class="paragraph">
- <p>Moving a character through your scene requires three things.</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>A navigation mesh.</p>
- </li>
- <li>
- <p>A path-finding component that uses that navigation mesh to calculate a path.</p>
- </li>
- <li>
- <p>A way to move the character.</p>
- </li>
- </ul>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="navmesh-creation"><a class="anchor" href="#navmesh-creation"></a>NavMesh Creation</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>The first thing you need for path-finding is a navigation mesh. There are two ways to generate the NavMesh, procedural or the jMonkey <a href="https://github.com/jMonkeyEngine/sdk/releases">SDK</a>.</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>The SDK has a built-in command, but comes with a trade-off that no parameter exceptions are thrown. This means you are flying blind when the NavMesh fails generation.</p>
- </li>
- <li>
- <p>If you choose procedural, you see any generation exceptions, but you will have to do a little more work like saving, loading and/or displaying the NavMesh.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Both methods produce exactly the same NavMesh and both will be covered in this tutorial.</p>
- </div>
- <div class="sect2">
- <h3 id="from-the-sdk"><a class="anchor" href="#from-the-sdk"></a>From the SDK</h3>
- <div class="ulist">
- <ul>
- <li>
- <p>Open your scene in the Terrain Editor or Scene Explorer by <b class="button">RMB</b> selecting the file in your assets folder and choosing <code>Edit Terrain</code> or <code>Edit in SceneComposer</code>.</p>
- </li>
- <li>
- <p>Once open, <b class="button">RMB</b> select the root node in the <code>SceneExplorer</code> and then select <code><span class="menuseq"><b class="menu">Spatial</b> <i class="fa fa-angle-right caret"></i> <b class="menuitem">NavMesh</b></span></code>.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>This will open the <code>Create NavMesh</code> dialog with default settings. You can read in depth about each parameter by following the <code>Configuration Parameters</code> link under <a href="#requirements">Requirements</a>.</p>
- </div>
- <div class="paragraph">
- <div class="title">Parameter Insight</div>
- <p>The jme3AI system uses CritterAI, which is based off <a href="https://github.com/recastnavigation/recastnavigation">Recast and Detour</a> navigation. The author of Recast lays out a few specific rules for NavMesh creation in this <a href="http://digestingduck.blogspot.dk/2009/08/recast-settings-uncovered.html">blog post</a>, which logically apply to jme3AI. Below is a translation of this post as it pertains to jme3AI.</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>First you should decide the size of your character "capsule". For example, if you are using meters as units in your game world, a good size of human sized character might be (r)adius=0.4, (h)eight=2.0.</p>
- </li>
- <li>
- <p>Next the voxelization cell size (cs) will be derived from that. Usually good value for cs is r/2 or r/3. In outdoor environments, r/2 might be enough, indoors you sometimes want the extra precision and you might choose to use r/3 or smaller.</p>
- </li>
- <li>
- <p>The voxelization cell height (ch) is defined separately in order to allow greater precision in height tests. Good starting point for ch is cs/2. If you get small holes where there are discontinuities in the height (steps), you may want to decrease cell height.</p>
- </li>
- <li>
- <p>Next up is the character definition values. First up is <code>minTraversableHeight</code>, which defines the height of the agent.</p>
- </li>
- <li>
- <p>The <code>maxTraversableStep</code> defines how high steps the character can climb.</p>
- </li>
- <li>
- <p>The parameter <code>traversableAreaBorderSize</code> defines the agent radius. If this value is greater than zero, the navmesh will be shrunken by the <code>traversableAreaBorderSize</code>. If you want to have tight fit navmesh, use zero radius.</p>
- </li>
- <li>
- <p>The parameter <code>maxTraversableSlope</code> is used before voxelization to check if the slope of a triangle is too high and those polygons will be given a non-walkable flag. The parameter is in radians.</p>
- </li>
- <li>
- <p>In certain cases really long outer edges may decrease the triangulation results. Sometimes this can be remedied by just tessellating the long edges. The parameter <code>maxEdgeLength</code> defines the max
- edge length. A good value for <code>maxEdgeLength</code> is something like <code>traversableAreaBorderSize*8</code>. A good way to tweak this value is to first set it really high and see if your data creates long edges. If so, then try to find as big value as possible which happen to create those few extra vertices which makes the tessellation better.</p>
- </li>
- <li>
- <p>When the rasterized areas are converted back to vectorized representation the <code>edgeMaxDeviation</code> describes how loosely the simplification is done. Good values are between 1.1-1.5 (1.3 usually yield good results). If the value is less, some stair-casing starts to appear at the edges and if it is more than that, the simplification starts to cut some corners.</p>
- </li>
- </ul>
- </div>
- <div class="admonitionblock note">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-note" title="Note"></i>
- </td>
- <td class="content">
- A summary of the parameter effects is included in the comments of the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavMeshState.java">NavMeshState.java</a> file and discussed in the Procedural code examples that follow this section.
- </td>
- </tr>
- </table>
- </div>
- <div class="paragraph">
- <p>If there are problems with your parameter settings, you will only know if the NavMesh doesn’t appear under the Node you selected and there is no task running in the status area located at the bottom right of the SDK.</p>
- </div>
- <div class="paragraph">
- <p>If the NavMesh doesn’t appear, then you will have to make adjustments to the <code>Configuration Parameters</code> until it completes successfully. Minor adjustments to cell size will usually work.</p>
- </div>
- <div class="admonitionblock caution">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-caution" title="Caution"></i>
- </td>
- <td class="content">
- Cell size has the greatest impact on your NavMesh. The smaller the cell size, the more accurate the NavMesh, the longer it takes to generate. Generating a 1024x1024 NavMesh can take anywhere from 30 seconds to ten minutes to complete, depending on terrain complexity. Even larger NavMeshes can take many hours.
- </td>
- </tr>
- </table>
- </div>
- <div class="admonitionblock tip">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-tip" title="Tip"></i>
- </td>
- <td class="content">
- Selecting the NavMesh node in the SceneExplorer will show the NavMesh in the Terrain Editor or SceneComposer view-port. If it doesn’t show, with the NavMesh node selected, change the <code>Cull Hint</code> to <code>Never</code> in the <code>NavMesh - Properties</code> panel.
- </td>
- </tr>
- </table>
- </div>
- </div>
- <div class="sect2">
- <h3 id="procedural-method"><a class="anchor" href="#procedural-method"></a>Procedural Method</h3>
- <div class="paragraph">
- <p>There are many ways to create a NavMesh. If you look at the constructor for the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/Jme3AI.java">Jme3AI.java</a> file, you will see I use a <a href="../../core/app/state/application_states.html#baseappstate" class="xref page">BaseAppState</a> named <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavMeshState.java">NavMeshState.java</a> which creates a <code>generator</code> object and builds the <code>NavMesh</code> new every time the program is ran.</p>
- </div>
- <div class="listingblock">
- <div class="title">Jme3AI constructor</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public Jme3AI() {
- super(new StatsAppState(), new DebugKeysAppState(), new TerrainState(),
- new NavMeshState(), new PCState(), new KeyboardRunState());
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>It can take from seconds to hours to build a NavMesh, depending on how complicated it is. Therefore, you would normally build the NavMesh or meshes, add them to your <code>Assets</code> folder and load them at startup. The <code>NavMeshState</code> and <code>NavMeshGenerator</code> classes are both convenience classes and are not required to create a NavMesh. If you wish to keep your game minimalist, you can set the variables for the CritterAI NavmeshGenerator (note the lower case 'm' in mesh) in the method call directly or by variable, and pass the IndexBuffer and VertexBuffer of your mesh into the CritterAI NavmeshGenerator object.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">NavmeshGenerator nmgen = new NavmeshGenerator(cellSize, cellHeight, minTraversableHeight,
- maxTraversableStep, maxTraversableSlope,
- clipLedges, traversableAreaBorderSize,
- smoothingThreshold, useConservativeExpansion,
- minUnconnectedRegionSize, mergeRegionSize,
- maxEdgeLength, edgeMaxDeviation, maxVertsPerPoly,
- contourSampleDistance, contourMaxDeviation);
- ...
- Get mesh buffers and set IntermediateData
- ...
- //Pass buffers and IntermediateData to build process
- TriangleMesh triMesh = nmgen.build(positions, indices, intermediateData);
- ...
- Process trimesh
- ...</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Let’s examine what it takes to create the <code>NavMesh</code> using the <code>NavMeshState</code> and <code>NavMeshGenerator</code> helper classes.</p>
- </div>
- <div class="listingblock">
- <div class="title">NavMeshState NavMesh generation method</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">/**
- * creates the NavMesh
- */
- private void createNavMesh() {
- generator = new NavMeshGenerator();
- //The width and depth resolution used when sampling the source geometry.
- //outdoors = agentRadius/2, indoors = agentRadius/3, cellSize =
- //agentRadius for very small cells.
- //Constraints > 0 , default=1
- generator.setCellSize(.25f);
- //The height resolution used when sampling the source geometry.
- //minTraversableHeight, maxTraversableStep, and contourMaxDeviation
- //will need to be greater than the value of cellHeight in order to
- //function correctly. maxTraversableStep is especially susceptible to
- //impact from the value of cellHeight.
- //cellSize/2
- //Constraints > 0, default=1.5
- generator.setCellHeight(.125f);
- //Represents the minimum floor to ceiling height that will still allow
- //the floor area to be considered traversable.
- //minTraversableHeight should be at least two times the value of
- //cellHeight in order to get good results. Max spatial height.
- //Constraints > 0, default=7.5
- generator.setMinTraversableHeight(2f);
- //Represents the maximum ledge height that is considered to still be
- //traversable.
- //maxTraversableStep should be greater than two times cellHeight.
- //Constraints >= 0, default=1
- generator.setMaxTraversableStep(0.3f);
- //The maximum slope that is considered traversable. (In degrees.)
- //Constraints >= 0, default=48
- generator.setMaxTraversableSlope(50.0f);
- //Indicates whether ledges should be considered un-walkable.
- //Constraints None, default=false
- generator.setClipLedges(false);
- //Represents the closest any part of a mesh can get to an obstruction in
- //the source geometry.
- //traversableAreaBorderSize value must be greater than the cellSize to
- //have an effect. Radius of the spatial.
- //Constraints >= 0, default=1.2
- generator.setTraversableAreaBorderSize(0.6f);
- //The amount of smoothing to be performed when generating the distance
- //field used for deriving regions.
- //Constraints >= 0, default=2
- generator.setSmoothingThreshold(0);
- //Applies extra algorithms to help prevent malformed regions from
- //forming.
- //Constraints None, default=true
- generator.setUseConservativeExpansion(true);
- //The minimum region size for unconnected (island) regions.
- //Constraints > 0, default=3
- generator.setMinUnconnectedRegionSize(8);
- //Any regions smaller than this size will, if possible, be merged with
- //larger regions.
- //Constraints >= 0, default=10
- generator.setMergeRegionSize(20);
- //The maximum length of polygon edges that represent the border of
- //meshes.
- //setTraversableAreaBorderSize * 8
- //Constraints >= 0, default=0
- generator.setMaxEdgeLength(4.0f);
- //The maximum distance the edges of meshes may deviate from the source
- //geometry.
- //1.1 to 1.5 for best results.
- //Constraints >= 0 , default=2.4
- generator.setEdgeMaxDeviation(1.3f);
- //The maximum number of vertices per polygon for polygons generated
- //during the voxel to polygon conversion process.
- //Constraints >= 3, default=6
- generator.setMaxVertsPerPoly(6);
- //Sets the sampling distance to use when matching the detail mesh to the
- //surface of the original geometry.
- //Constraints >= 0, default=25
- generator.setContourSampleDistance(5.0f);
- //The maximum distance the surface of the detail mesh may deviate from
- //the surface of the original geometry.
- //Constraints >= 0, default=25
- generator.setContourMaxDeviation(5.0f);
- //Time allowed before generation process times out in milliseconds.
- //default=10000
- generator.setTimeout(40000);
- //the data object to use for storing data related to building the
- //navigation mesh.
- IntermediateData data = new IntermediateData();
- generator.setIntermediateData(data);
- Mesh mesh = new Mesh();
- GeometryBatchFactory.mergeGeometries(findGeometries(app.getRootNode(),
- new LinkedList<>(), generator), mesh);
- //uncomment to show mesh
- // Geometry meshGeom = new Geometry("MeshGeometry");
- // meshGeom.setMesh(mesh);
- // showGeometry(meshGeom, ColorRGBA.Yellow);
- // saveNavMesh(meshGeom);
- Mesh optiMesh = generator.optimize(mesh);
- navMesh.loadFromMesh(optiMesh);
- Geometry geom = new Geometry(DataKey.NAVMESH);
- geom.setMesh(optiMesh);
- //display the mesh
- showGeometry(geom, ColorRGBA.Green);
- //save the navmesh to Scenes/NavMesh for loading
- exportNavMesh(geom, DataKey.NAVMESH);
- //save geom to rootNode if you wish
- saveNavMesh(geom);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>First, we create the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavMeshGenerator.java">NavMeshGenerator</a> object and then use it to set the parameters for the NavMesh.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">generator = new NavMeshGenerator();
- ...
- generator.setCellSize(.25f);
- ...</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>In our next step we create an IntermediateData object.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//the data object to use for storing data related to building the
- //navigation mesh.
- IntermediateData data = new IntermediateData();
- generator.setIntermediateData(data);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The IntermediateData object can be used to get information about the build process of the NavMesh such as build times. You query this object after building the NavMesh. If you don’t wish to see the data, set it to null.</p>
- </div>
- <div class="paragraph">
- <p>At this point, you now have a <code>generator</code> object that you use to create the NavMesh with.</p>
- </div>
- <div class="paragraph">
- <p>Included in the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavMeshState.java">NavMeshState.java</a> file is the helper method <code>findGeometries</code>.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//Gathers all geometries in supplied node into supplied List. Uses
- //NavMeshGenerator to merge found Terrain meshes into one geometry prior to
- //adding. Scales and sets translation of merged geometry.
- private List<Geometry> findGeometries(Node node, List<Geometry> geoms,
- NavMeshGenerator generator)</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>It is used to collect all geometries, attached to a node, into a List. If a child of the node is a Terrain instance (which can consist of many meshes), it will use the <code>generator</code> object to merge them into one mesh, then scale and set translation of the merged mesh prior to being added to the list. You then use GeometryBatchFactory to merge all the geometries in the list into a single <code>mesh</code> object.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Mesh mesh = new Mesh();
- GeometryBatchFactory.mergeGeometries(findGeometries(app.getRootNode(),
- new LinkedList<>(), generator), mesh);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>After these methods execute, you have a single <code>mesh</code> object that is now ready to be optimized.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Mesh optiMesh = generator.optimize(mesh);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This is where the parameters you set with the <code>generator</code> object are applied to the supplied <code>mesh</code>. The optimize method will return a new Mesh object that reflects your generator settings. Now is when any problems with your parameters will show themselves as either warnings or exceptions. You should keep changing the various parameters, one at a time and in small increments/decrements, until your <code>mesh</code> generates with no errors. See each parameter’s notes for suggestions on how to do so.</p>
- </div>
- <div class="paragraph">
- <p>After the mesh generates, you need to link all of its cells together so it can be used as your <code>NavMesh</code> object. You do this by calling <code>loadFromMesh()</code> or <code>loadFromData()</code>, depending on your implementation, on your <code>optiMesh</code> object.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">navMesh.loadFromMesh(optiMesh);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If you look at the second constructor for the <code>NavMesh</code> class you will see this is all it does. You would use this constructor if you were loading a <code>Mesh</code> from a geometry that had already been optimized and saved into your <code>Assets</code> folder for example.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public NavMesh(Mesh mesh) {
- loadFromMesh(mesh);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The <code>NavMesh</code> object is now ready for use in your game, but you still need to create the geometry for it if you wish to save or view it. You do this the same as you would for any newly created mesh.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Geometry geom = new Geometry(DataKey.NAVMESH);
- geom.setMesh(navMesh);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Now that you have your Mesh you should save it.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//save the navmesh to Scenes/NavMesh for loading
- exportNavMesh(geom, DataKey.NAVMESH);
- //save geom to rootNode if you wish
- saveNavMesh(geom);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>In this instance, the object is exported to the projects <code>Assets</code> folder so it can be loaded rather than generated every time the game starts. This is the preferred method. The <code>saveNavMesh()</code> method just attaches the geometry to the <code>rootNode</code>. How and where you choose to save depends on your implementation and personal preferences.</p>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="pathfinding"><a class="anchor" href="#pathfinding"></a>Pathfinding</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>There are many ways to implement the <code>NavMeshPathfinder</code> class of the jme3AI library. You can create a control, instantiate the <code>NavMeshPathFinder</code> class, and query the newly created object in a thread. You could use a single AppState to calculate all your paths. You could, as in this tutorial, extend the NavMeshPathFinder class in a custom control.</p>
- </div>
- <div class="paragraph">
- <p>You also need a way to communicate <code>Vector3f</code> changes to the <code>NavMeshPathfinder</code>. This tutorial uses an ActionListener and Interface. You could just as easily create a public method in the control, and call it from the ActionListener, or store the <code>Vector3f</code> in <code>UserData</code> and look for changes from the control itself.</p>
- </div>
- <div class="paragraph">
- <p>These are implementation decisions that are left up to you.</p>
- </div>
- <div class="sect2">
- <h3 id="loading-the-navmesh"><a class="anchor" href="#loading-the-navmesh"></a>Loading the NavMesh</h3>
- <div class="paragraph">
- <p>In this tutorial example, the optimized mesh was exported as a geometry using the jMonkey binary format <code>.j3o</code>. Doing so means the loading of your <code>NavMeshes</code> is done the same way you load any model, by using the <code>AssetManager</code>. Once you load the <code>.j3o</code>, you grab its <code>Mesh</code> and create the <code>NavMesh</code> object to be passed to the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavigationControl.java">NavigationControl</a> constructor. This tutorial uses a <a href="../../core/app/state/application_states.html#baseappstate" class="xref page">BaseAppState</a> for model loading so access to the <code>Application</code> class is built in.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//load NavMesh geometry saved to assets folder
- Geometry navGeom = (Geometry) getApplication().getAssetManager().
- loadModel("Scenes/NavMesh/NavMesh.j3o");
- NavigationControl navControl = new NavigationControl(new NavMesh(
- navGeom.getMesh()), getApplication(), true)
- charNode.addControl(navControl);
- //NavigationControl implements Pickable Interface
- picked = navControl;</code></pre>
- </div>
- </div>
- <div class="admonitionblock note">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-note" title="Note"></i>
- </td>
- <td class="content">
- <div class="paragraph">
- <p>This tutorial uses a custom control, <code>NavigationControl</code>, that extends the <code>NavMeshPathfinder</code> class. As this is a tutorial, some extra variables are used for displaying the navigation path and are not needed. The constructor for <code>NavMeshPathfinder</code> requires just the the passing of the <code>NavMesh</code> object, which makes for a cleaner control.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public NavigationControl(NavMesh navMesh) {
- ...
- }</code></pre>
- </div>
- </div>
- </td>
- </tr>
- </table>
- </div>
- </div>
- <div class="sect2">
- <h3 id="communicating-with-navigationcontrol"><a class="anchor" href="#communicating-with-navigationcontrol"></a>Communicating with NavigationControl</h3>
- <div class="paragraph">
- <p>This tutorial makes use of the <a href="../../tutorials/beginner/hello_picking.html" class="xref page">Hello Picking</a> and <a href="../../core/input/mouse_picking.html#pick-a-target-using-the-mouse-pointer" class="xref page">Mouse Picking</a> tutorials so you should already be familiar with this method for picking and how to add the <a href="../../tutorials/beginner/hello_input_system.html" class="xref page">input mappings</a> to your game. How you implement your ActionListener is up to you.</p>
- </div>
- <div class="listingblock">
- <div class="title">PCState ActionListener</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> private class ClickedListener implements ActionListener {
- @Override
- public void onAction(String name, boolean isPressed, float tpf) {
- if (name.equals(ListenerKey.PICK) && !isPressed) {
- CollisionResults results = new CollisionResults();
- Vector2f click2d = getInputManager().getCursorPosition().clone();
- Vector3f click3d = app.getCamera().getWorldCoordinates(click2d,
- 0f).clone();
- Vector3f dir = app.getCamera().getWorldCoordinates(
- click2d, 1f).subtractLocal(click3d).normalizeLocal();
- Ray ray = new Ray(click3d, dir);
- app.getRootNode().collideWith(ray, results);
- for (int i = 0; i < results.size(); i++) {
- // For each hit, we know distance, impact point, name of geometry.
- float dist = results.getCollision(i).getDistance();
- Vector3f pt = results.getCollision(i).getContactPoint();
- String hit = results.getCollision(i).getGeometry().getName();
- System.out.println("* Collision #" + i);
- System.out.println(
- " You shot " + hit
- + " at " + pt
- + ", " + dist + " wu away.");
- }
- if (results.size() > 0) {
- // The closest collision point is what was truly hit:
- CollisionResult closest = results.getClosestCollision();
- // Let's interact - we mark the hit with a red dot.
- mark.setLocalTranslation(closest.getContactPoint());
- app.getRootNode().attachChild(mark);
- picked.setTarget(closest.getContactPoint());
- System.out.println(" Closest Contact " + closest.
- getContactPoint());
- } else {
- // No hits? Then remove the red mark.
- app.getRootNode().detachChild(mark);
- }
- }
- }
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The main line of interest here is,</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">picked.setTarget(closest.getContactPoint());</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>where <code>picked</code> is the reference object used to communicate our <code>Vector3f</code> changes to the <code>NavigationControl</code>.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//NavigationControl implements Pickable Interface
- picked = navControl;</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>At this point you have loaded your <code>NavMesh</code>, added the <code>NavigationControl</code> to your spatial, and instituted a method for communicating with the <code>NavMeshPathFinder</code>. Next we will delve into the details of the <code>NavigationControl</code>.</p>
- </div>
- </div>
- <div class="sect2">
- <h3 id="navigationcontrol"><a class="anchor" href="#navigationcontrol"></a>NavigationControl</h3>
- <div class="paragraph">
- <p>The <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/ai/NavigationControl.java">NavigationControl</a> is a <a href="../../core/scene/control/custom_controls.html" class="xref page">custom control</a> that extends the <a href="https://github.com/MeFisto94/jme3-artificial-intelligence/blob/master/AI/src/com/jme3/ai/navmesh/NavMeshPathfinder.java">NavMeshPathFinder</a> class of the Jme3AI library and implements the <code>Pickable</code> interface.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class NavigationControl extends NavMeshPathfinder implements Control,
- JmeCloneable, Pickable {
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/interfaces/Pickable.java">Pickable</a> interface is straightforward and its sole purpose in this implementation is to communicate changes made to the pick target.</p>
- </div>
- <div class="listingblock">
- <div class="title">Pickable Interface implementation</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">/**
- * @param target the target to set
- */
- @Override
- public void setTarget(Vector3f target) {
- this.target = target;
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The heartbeat of the control lies in the pathfinding thread which makes calls to the <code>computePath()</code> method. Potentially long running tasks like this should always be ran from a thread. Below, is the constructor you would normally use to instantiate your control.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public NavigationControl(NavMesh navMesh) {
- super(navMesh); //sets the NavMesh for this control
- executor = Executors.newScheduledThreadPool(1);
- startPathFinder();
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>First, you call <code>super(navMesh)</code> to set the <code>NavMesh</code> for the control, then setup your <code>ExecutorService</code> and start the pathfinding thread.</p>
- </div>
- <div class="paragraph">
- <p>This is a custom thread implementation so it’s up to you to handle shutting it down. This is done in the controls <code>setSpatial()</code> method.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (spatial == null) {
- shutdownAndAwaitTermination(executor);
- ...
- } else {
- ...
- }</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="title">Executor shutdown process</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//standard shutdown process for executor
- private void shutdownAndAwaitTermination(ExecutorService pool) {
- pool.shutdown(); // Disable new tasks from being submitted
- try {
- // Wait a while for existing tasks to terminate
- if (!pool.awaitTermination(6, TimeUnit.SECONDS)) {
- pool.shutdownNow(); // Cancel currently executing tasks
- // Wait a while for tasks to respond to being cancelled
- if (!pool.awaitTermination(6, TimeUnit.SECONDS)) {
- LOG.log(Level.SEVERE, "Pool did not terminate {0}", pool);
- }
- }
- } catch (InterruptedException ie) {
- // (Re-)Cancel if current thread also interrupted
- pool.shutdownNow();
- // Preserve interrupt status
- Thread.currentThread().interrupt();
- }
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The easiest way to move a physics character is by using the <a href="../../physics/control/walking_character.html#bettercharactercontrol" class="xref page">BetterCharacterControl</a> class. In this implementation, this is done in the <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/controls/PCControl.java">PCControl</a> class by extending <code>BetterCharacterControl</code>. Since <code>BetterCharacterControl</code> is required to be present on the spatial for pathfinding, in the <code>setSpatial()</code> method, we throw an exception to let us know if it’s missing.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (spatial == null) {
- ...
- } else {
- pcControl = spatial.getControl(PCControl.class);
- if (pcControl == null) {
- throw new IllegalStateException(
- "Cannot add NavigationControl to spatial without PCControl!");
- }
- }</code></pre>
- </div>
- </div>
- </div>
- <div class="sect2">
- <h3 id="pathfinding-thread"><a class="anchor" href="#pathfinding-thread"></a>Pathfinding Thread</h3>
- <div class="listingblock">
- <div class="title">NavigationControl pathfinding thread</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//Computes a path using the A* algorithm. Every 1/2 second checks target
- //for processing. Path will remain until a new path is generated.
- private void startPathFinder() {
- executor.scheduleWithFixedDelay(() -> {
- if (target != null) {
- clearPath();
- setWayPosition(null);
- pathfinding = true;
- //setPosition must be set before computePath is called.
- setPosition(spatial.getWorldTranslation());
- //warpInside(target) moves endpoint within the navMesh always.
- warpInside(target);
- System.out.println("Target " + target);
- boolean success;
- //compute the path
- success = computePath(target);
- System.out.println("SUCCESS = " + success);
- if (success) {
- //clear target if successful
- target = null;
- ...
- }
- pathfinding = false;
- }
- }, 0, 500, TimeUnit.MILLISECONDS);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>How you setup your pathfinding thread makes a significant difference.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">executor.scheduleWithFixedDelay(() -> {
- ...
- }, 0, 500, TimeUnit.MILLISECONDS);</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This <code>ExecutorService</code> is set to start immediately (0) with a fixed delay of (500) milliseconds. This means the task has a fixed delay of 1/2 second between the end of an execution and the start of the next execution, i.e. it doesn’t take into account the actual duration of the task. If you were to use <code>scheduleAtFixedRate()</code>, you risk that the task doesn’t complete in the time allocated.</p>
- </div>
- <div class="paragraph">
- <p>When you use the <code>BetterCharacterControl</code>, all that’s required to move the spatial is that you <code>setWalkDirection()</code> and the spatial will continuously move in that direction. The following code breakdown explains how the <code>NavigationControl</code> takes advantage of this.</p>
- </div>
- <div class="paragraph">
- <p>It starts by having the pathfinding thread check a <code>target</code> variable for changes.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (target != null) {
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If it finds a target, it will compute a new path to that <code>target</code>, and if successful, update the <code>NavMeshPathfinder</code> path variable. The <code>update()</code> loop of the control continuously checks this path variable, and if its non-null, takes an appropriate action.</p>
- </div>
- <div class="paragraph">
- <p>Before you compute the path you first clear the existing path, and set wayPosition to null.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (target != null) {
- clearPath();
- setWayPosition(null);
- pathfinding = true;
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Doing this allows the player to select a new <code>target</code> at any time and immediately start moving along the new path. Otherwise, the character must finish the path they are on, then backtrack to the position the character was at when the <code>target</code> change was made, before then continuing on the new path.</p>
- </div>
- <div class="paragraph">
- <p>Next, you must call <code>setPosition()</code> <strong>before</strong> calling the <code>computePath()</code> method.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (target != null) {
- ...
- setPosition(spatial.getWorldTranslation());
- ...
- //compute the path
- success = computePath(target);
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>There are some things you need to know about how a path is computed.</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>The first waypoint on any path is the one you set with <code>setPosition()</code>.</p>
- </li>
- <li>
- <p>The last waypoint on any path is always the <code>target</code> Vector3f.</p>
- </li>
- <li>
- <p>computePath() adds one waypoint to the cell <strong>nearest</strong> to the target only if you are not in the goalCell (the cell target is in), and if there is a cell between first and last waypoint, and if there is no direct line of sight.</p>
- </li>
- <li>
- <p>If inside the goalCell when a new target is selected, computePath() will do a direct line of sight placement of target. This means there will only be two waypoints set, <code>setPosition()</code> and <code>target</code>.</p>
- </li>
- <li>
- <p>If the <code>target</code> is outside the <code>NavMesh</code>, your endpoint will be as well.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>To guarantee that <code>target</code> is always inside the <code>NavMesh</code>, call</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (target != null) {
- ...
- //warpInside(target) moves endpoint within the navMesh always.
- warpInside(target);
- ...
- //compute the path
- success = computePath(target);
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>before calling <code>computePath()</code> and the endpoint of the path will be moved to the closest cell to the <code>target</code> that’s inside the <code>NavMesh</code>.</p>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="character-movement"><a class="anchor" href="#character-movement"></a>Character Movement</h2>
- <div class="sectionbody">
- <div class="listingblock">
- <div class="title">NavigationControl update() loop</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
- public void update(float tpf) {
- if (getWayPosition() != null) {
- Vector3f spatialPosition = spatial.getWorldTranslation();
- Vector2f aiPosition = new Vector2f(spatialPosition.x,
- spatialPosition.z);
- Vector2f waypoint2D = new Vector2f(getWayPosition().x,
- getWayPosition().z);
- float distance = aiPosition.distance(waypoint2D);
- //move char between waypoints until waypoint reached then set null
- if (distance > .25f) {
- Vector2f direction = waypoint2D.subtract(aiPosition);
- direction.mult(tpf);
- pcControl.setViewDirection(new Vector3f(direction.x, 0,
- direction.y).normalize());
- pcControl.onAction(ListenerKey.MOVE_FORWARD, true, 1);
- } else {
- setWayPosition(null);
- }
- } else if (!isPathfinding() && getNextWaypoint() != null
- && !isAtGoalWaypoint()) {
- if (showPath) {
- showPath();
- showPath = false;
- }
- //advance to next waypoint
- goToNextWaypoint();
- setWayPosition(new Vector3f(getWaypointPosition()));
- //set spatial physical position
- if (getPositionType() == EnumPosition.POS_STANDING.position()) {
- setPositionType(EnumPosition.POS_RUNNING.position());
- stopFeetPlaying();
- stopTorsoPlaying();
- }
- } else {
- //waypoint null so stop moving and set spatials physical position
- if (getPositionType() == EnumPosition.POS_RUNNING.position()) {
- setPositionType(EnumPosition.POS_STANDING.position());
- stopFeetPlaying();
- stopTorsoPlaying();
- }
- pcControl.onAction(ListenerKey.MOVE_FORWARD, false, 1);
- }
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If the <code>computePath()</code> successfully computes a new path, the path variable of the <code>NavMeshPathfinder</code> will no longer be null. The update loop of the <code>NavigationControl</code> checks this path variable, every iteration that wayPosition is null, by calling the <code>getNextWaypoint()</code> method. If the path has another waypoint, it will advance to the next position in the path and set the <code>wayPosition</code> variable of the <code>NavigationControl</code> to that position.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">} else if (!isPathfinding() && getNextWaypoint() != null
- && !isAtGoalWaypoint()) {
- ...
- //advance to next waypoint
- goToNextWaypoint();
- setWayPosition(new Vector3f(getWaypointPosition()));
- ...
- }</code></pre>
- </div>
- </div>
- <div class="admonitionblock important">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-important" title="Important"></i>
- </td>
- <td class="content">
- Remember, the first waypoint in the path is always the spatials current position. This is why you always advance the position first.
- </td>
- </tr>
- </table>
- </div>
- <div class="paragraph">
- <p>On the next iteration of the controls <code>update()</code> method, it sees that <code>wayPosition</code> is no longer null and calculates the distance from the spatials current position to the <code>wayPosition</code>.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (getWayPosition() != null) {
- Vector3f spatialPosition = spatial.getWorldTranslation();
- Vector2f aiPosition = new Vector2f(spatialPosition.x,
- spatialPosition.z);
- Vector2f waypoint2D = new Vector2f(getWayPosition().x,
- getWayPosition().z);
- float distance = aiPosition.distance(waypoint2D);
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If it’s greater than the distance specified, it will <code>setViewDirection()</code> of the <code>PCControl</code> (which extends BetterCharacterControl) and then notify the <code>PCControl</code> that the spatial can move by calling the controls <code>onAction()</code> method directly.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (getWayPosition() != null) {
- ...
- //move char between waypoints until waypoint reached then set null
- if (distance > .25f) {
- Vector2f direction = waypoint2D.subtract(aiPosition);
- direction.mult(tpf);
- pcControl.setViewDirection(new Vector3f(direction.x, 0,
- direction.y).normalize());
- pcControl.onAction(ListenerKey.MOVE_FORWARD, true, 1);
- } else {
- ...
- }
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>It’s up to the <code>NavigationControl</code> to determine when the character should stop moving. Each time the spatial reaches a point that is less than the specified distance, it sets the wayPosition to null.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if (distance > .25f) {
- ...
- } else {
- setWayPosition(null);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If the path position has not yet reached the end, it will once again be advance to the next waypoint in the path and update the wayPosition.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">} else if (!isPathfinding() && getNextWaypoint() != null
- && !isAtGoalWaypoint()) {
- ...
- //advance to next waypoint
- goToNextWaypoint();
- setWayPosition(new Vector3f(getWaypointPosition()));
- ...
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>When the last waypoint is reached, the <code>NavigationControl</code> notifies the <code>PCControl</code> that the spatial can no longer move.</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">} else {
- ...
- pcControl.onAction(ListenerKey.MOVE_FORWARD, false, 1);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The <a href="https://github.com/jMonkeyEngine/doc-examples/blob/master/src/com/jme3/examples/jme3ai/controls/PCControl.java">PCControl</a> class handles the actual movement of the spatial in its <code>update()</code> loop. It does this by checking the <code>forward</code> variable every iteration. This variable is set when you call the <code>onAction()</code> method from the <code>NavigationControl</code> update loop.</p>
- </div>
- <div class="listingblock">
- <div class="title">PCControl ActionListener</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
- public void onAction(String name, boolean isPressed, float tpf) {
- if (name.equals(ListenerKey.MOVE_FORWARD)) {
- forward = isPressed;
- }
- }</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="title">PCControl update() loop</div>
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
- public void update(float tpf) {
- super.update(tpf);
- this.moveSpeed = 0;
- walkDirection.set(0, 0, 0);
- if (forward) {
- Vector3f modelForwardDir = spatial.getWorldRotation().mult(Vector3f.UNIT_Z);
- position = getPositionType();
- for (EnumPosition pos : EnumPosition.values()) {
- if (pos.position() == position) {
- switch (pos) {
- case POS_RUNNING:
- moveSpeed = EnumPosition.POS_RUNNING.speed();
- break;
- default:
- moveSpeed = 0f;
- break;
- }
- }
- }
- walkDirection.addLocal(modelForwardDir.mult(moveSpeed));
- }
- setWalkDirection(walkDirection);
- }</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The <code>PCControl</code> will then set the walk direction, based off spatials world rotation, and set the speed.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="conclusion"><a class="anchor" href="#conclusion"></a>Conclusion</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>The intent of this tutorial was to give you a general breakdown of how the Jme3AI navigation system works as well as demonstrate how flexible its implementation is. All the code in this tutorial is free for your use and can be found in the <a href="https://github.com/jMonkeyEngine/doc-examples">jme3 documentation repository</a>. The implementations design is such that you can easily change each of the parameters and then visually see how they affect the NavMesh. If you have questions or suggestions on improving this tutorial you can do so in the <a href="https://hub.jmonkeyengine.org/">jMonkeyEngine forum</a>.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="other-ai-options"><a class="anchor" href="#other-ai-options"></a>Other AI Options</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>There are other jME3 specific options available you can read about in the wiki under the topic <a href="https://wiki.jmonkeyengine.org/docs/jme3.html#artificial-intelligence-ai">Artificial Intelligence (AI)</a>.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="further-reading"><a class="anchor" href="#further-reading"></a>Further Reading</h2>
- <div class="sectionbody">
- <div class="ulist">
- <ul>
- <li>
- <p><a href="../_attachments/Astar.pdf">A* path-finding for Beginners</a> by Patrick Lester</p>
- </li>
- <li>
- <p><a href="http://natureofcode.com/book/">The Nature of Code</a> by Daniel Shiffman</p>
- </li>
- <li>
- <p><a href="http://www.red3d.com/cwr/steer/gdc99/">Steering Behaviors For Autonomous Characters</a> by Craig W. Reynolds</p>
- </li>
- <li>
- <p><a href="http://www.critterai.org/projects/nmgen_study/">Study: Navigation Mesh Generation Java</a> by Stephen Pratt</p>
- </li>
- </ul>
- </div>
- </div>
- </div>
- <div id="footnotes">
- <hr>
- <div class="footnote" id="_footnotedef_1">
- <a href="#_footnoteref_1">1</a>. Path-finding means computing the shortest route between two points. Usually mazes.
- </div>
- <div class="footnote" id="_footnotedef_2">
- <a href="#_footnoteref_2">2</a>. Path-following is taking a path that already exists and then following that path.
- </div>
- </div>
- <nav class="pagination">
- <span class="prev"><a href="steer_behaviours.html">Steer Behaviours</a></span>
- <span class="next"><a href="../gui/topic_contributions_gui.html">GUI</a></span>
- </nav>
- </article>
- <aside class="toc sidebar" data-title="Contents" data-levels="2">
- <div class="toc-menu"></div>
- </aside>
- </div>
- </main>
- </div>
- <footer class="footer">
- <p>Copyright 2020 jMonkeyEngine Wiki Contributors. Licensed BSD-3.</p>
- </footer>
- <script src="../../../../_/js/vendor/docsearch.min.js"></script>
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js -->
- <script>
- var search = docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#search-input',
- autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
- algoliaOptions: { hitsPerPage: 10 }
- }).autocomplete
- search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
- function focusSearchInput () { document.querySelector('#search-input').focus() }
- if (document.querySelector('.home-link.is-current')) window.addEventListener('load', focusSearchInput)
- </script>
- <script src="../../../../_/js/site.js"></script>
- <script async src="../../../../_/js/vendor/highlight.js"></script>
- </body>
- </html>
|