clearListeners() </td><td>Adds or removes listeners to receive animation related events.</td>
</tr>
</table></div>
<!-- EDIT8 TABLE [4347-4816] --><div><table>
<!-- EDIT8 TABLE [4360-4829] --><div><table>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
@ -173,7 +173,7 @@ removeAnim(boneAnim)</td><td>Adds or removes an animation from this Control.</td
<td>getAnimationLength("anim")</td><td>Returns the length of the given named animation in seconds</td>
</tr>
</table></div>
<!-- EDIT9 TABLE [4818-5378] --><div><table>
<!-- EDIT9 TABLE [4831-5391] --><div><table>
<tr>
<th>AnimControl Property</th><th>Usage</th>
</tr>
@ -187,9 +187,9 @@ removeAnim(boneAnim)</td><td>Adds or removes an animation from this Control.</td
<td>getAttachmentsNode("bone")</td><td>Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone's motions.</td>
</tr>
</table></div>
<!-- EDIT10 TABLE [5380-5695] -->
<!-- EDIT10 TABLE [5393-5708] -->
</div>
<!-- EDIT7 SECTION "Animation Control Properties" [4245-5697] -->
<!-- EDIT7 SECTION "Animation Control Properties" [4258-5710] -->
<h2><a>Animation Channel Properties</a></h2>
<div>
@ -218,7 +218,7 @@ The following properties are set per AnimChannel.
<td>setTime(1.3f); </td><td> Fast-forward or rewind to a certain moment in time of this animation. </td>
</tr>
</table></div>
<!-- EDIT12 TABLE [5791-6415] -->
<!-- EDIT12 TABLE [5804-6428] -->
<p>
The following information is available for a channel.
@ -244,7 +244,7 @@ The following information is available for a channel.
<td>getControl()</td><td>The AnimControl that belongs to this AnimChannel.</td>
</tr>
</table></div>
<!-- EDIT13 TABLE [6472-7105] -->
<!-- EDIT13 TABLE [6485-7118] -->
<p>
Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs).
@ -270,9 +270,9 @@ addToRootBone(bone1) </td><td>Add a series of bones to be influenced by this ani
addFromRootBone(bone1) </td><td>Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.</td>
@ -290,14 +290,14 @@ Animations are played by channel. <strong>Note:</strong> Whether the animation c
The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.</td>
</tr>
</table></div>
<!-- EDIT16 TABLE [8154-8480] -->
<!-- EDIT16 TABLE [8167-8493] -->
<p>
<strong>Tip:</strong> Use the AnimEventLister below to react at the end or start of an animation cycle.
@ -62,20 +62,20 @@ You can! This is what AppStates are there for. An AppState class is subset of (o
<p>
Each AppState lets you define what happens in the following situations:
Each AppState lets you define what happens to it in the following situations:
</p>
<ul>
<li><div><strong>The AppState is initialized:</strong> You load and initialize game data, InputHandlers, AppStates and Controls and attach nodes. <br/>
The AppState has its own simpleInitApp() method, so to speak.</div>
The AppState executes its own simpleInitApp() method when it is attached, so to speak.</div>
</li>
<li><div><strong>The AppState has been enabled (unpaused):</strong> This toggles a boolean isEnabled() to true. Here you attach nodes and listeners that should become active while it's running. </div>
</li>
<li><div><strong>While the AppState is running/paused:</strong> You can poll isEnabled() to define paused and unpaused game behaviour in the update() loop that. Polls and modify the game state, modify the scene graph, and triggers events. If !isEnabled(), write code that skips the running sections of this AppState's <code>update()</code> loop. <br/>
<li><div><strong>While the AppState is running/paused:</strong> You can poll isEnabled() to define paused and unpaused game behaviour in the update() loop. In update(), you poll and modify the game state, modify the scene graph, and trigger events. Test if <code>!isEnabled()</code>, and write code that skips the running sections of this AppState's <code>update()</code> loop. <br/>
Each AppState has its own update loop, which hooks into the main simpleUpdate() loop (callback). </div>
</li>
<li><div><strong>The AppState has been disabled (paused):</strong> This toggles a boolean isEnabled() to false. Switch to your specific "paused" state. </div>
<li><div><strong>The AppState has been disabled (paused):</strong> This toggles a boolean isEnabled() to false. Here you switch all objects to their specific "paused" behaviour. </div>
</li>
<li><div><strong>The AppState is cleaned up:</strong> Here you decide whether to save this AppState's game state, unregister Controls and InputHandlers, detach related AppStates, and detach nodes from the rootNode.</div>
<li><div><strong>The AppState is cleaned up:</strong> Here you decide what happens when the AppState is detached. Save this AppState's game state, unregister Controls and InputHandlers, detach related AppStates, detach nodes from the rootNode, etc.</div>
</li>
</ul>
@ -86,7 +86,7 @@ Each AppState has its own update loop, which hooks into the main simpleUpdate()
Note: this tutorial needs to be fixed and is currently not correct. One should almost never override stateDetached and stateAttached??? and should certainly never do anything scene related in them.
</p>
<p>
This demo is a simple example of how you use AppStates to toggle between a StartScreen and a SettingsScreen (press RETURN) while the game is paused, and start the game by switching to a GameRunning state (press BACKSPACE).
</p>
<p>
There are four files, Main.java, GameRunningState.java, StartScreenState.java, SettingsScreenState.java.
<li><div> The paths stay the same, no matter whether the game runs on Windows, Mac, Linux, etc!</div>
</li>
<li><div> The AssetManager automatically optimizes the handling of OpenGL objects. <br/>
<li><div> The AssetManager automatically caches and optimizes the handling of OpenGL objects. <br/>
For example, the same textures are not uploaded to the graphics card multiple times when multiple models use them.</div>
</li>
<li><div> The <ahref="/com/jme3/gde/docs/sdk/default_build_script.html">default build script</a> automatically bundles the contents of the <code>assets</code> directory into the executable. </div>
@ -43,7 +43,7 @@ See also <a href="/com/jme3/gde/docs/jme3/intermediate/best_practices.html">Best
</p>
</div>
<!-- EDIT1 SECTION "AssetManager" [1-1691] -->
<!-- EDIT1 SECTION "AssetManager" [1-1702] -->
<h2><a>Usage</a></h2>
<div>
@ -71,7 +71,7 @@ Additionally, you can configure the Asset Manager and add any path to its root.
</p>
</div>
<!-- EDIT2 SECTION "Usage" [1692-2849] -->
<!-- EDIT2 SECTION "Usage" [1703-2860] -->
<h2><a>Asset Directory</a></h2>
<div>
@ -119,7 +119,7 @@ After the conversion, you move the .j3o file into the <code>assets/Models/</code
The flyby camera is an AppState that extends the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and strafing to the sides; move the mouse to rotate the camera ("Mouse Look"), scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera vertically.
The <code>flyCam</code> class field gives you access to an AppState that extends the default camera in <code>com.jme3.app.SimpleApplication</code> with more features. The input manager of the <code>com.jme3.input.FlyByCamera</code> AppState is preconfigured to respond to the WASD keys for walking forwards and backwards, and strafing to the sides; move the mouse to rotate the camera ("Mouse Look"), scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera vertically.
</p>
<pre>Q W up forw
A S D --> left back right
Z down </pre>
<div><table>
<tr>
<th>Method</th><th>Usage</th>
@ -114,15 +121,20 @@ The flyby camera is an AppState that extends the default camera in com.jme3.app.
<td>flyCam.setDragToRotate(true)</td><td>Forces the player to keep mouse button pressed to rotate camera, typically used for Applets. If false (default), all mouse movement will be captured and interpreted as rotations.</td>
</tr>
</table></div>
<!-- EDIT5 TABLE [2326-2708] -->
<!-- EDIT5 TABLE [2634-3016] -->
<p>
The FlyByCamera is active by default, but you can change all these defaults for your game.
</p>
</div>
<!-- EDIT4 SECTION "FlyBy Camera" [1941-2709] -->
<!-- EDIT4 SECTION "FlyBy Camera" [2036-3109] -->
<h2><a>Chase Camera</a></h2>
<div>
<p>
jME3 also supports a Chase Cam that can follow a moving target Spatial (<code>com.jme3.input.ChaseCamera</code>). Click and hold the mouse button to rotate around the target.
jME3 also supports an optional Chase Cam that can follow a moving target Spatial (<code>com.jme3.input.ChaseCamera</code>). When you use the chase cam, the player clicks and hold the mouse button to rotate the camera around the camera target. You can use a chase cam if you need the mouse pointer visible in your game.
</p>
<pre>flyCam.setEnabled(false);
ChaseCamera chaseCam = new ChaseCamera(cam, target, inputManager);</pre>
<td>chaseCam.setDefaultHorizontalRotation(-FastMath.PI/2);</td><td>The default horizontal rotation angle of the camera around the target at the start of the application.</td>
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.adobe.com/products/flashplayer/"><paramname="text"value="<html><u>Adobe Flash Plugin</u></html>"><paramname="textColor"value="blue"></object> is needed to display this content.
</object>
<!-- <![endif]-->
@ -596,20 +600,20 @@ The <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param
The <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://www.adobe.com/products/flashplayer/"><paramname="text"value="<html><u>Adobe Flash Plugin</u></html>"><paramname="textColor"value="blue"></object> is needed to display this content.
</object>
<!-- <![endif]-->
@ -617,7 +621,7 @@ The <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param
</p>
</div>
<!-- EDIT7 SECTION "Using Advanced features to Record from more than one perspective at once" [17185-17326] -->
<!-- EDIT7 SECTION "Using Advanced features to Record from more than one perspective at once" [17232-17373] -->
JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. Combined with screen recording software, you use cinematics to create <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Cutscene"><paramname="text"value="<html><u>cutscenes</u></html>"><paramname="textColor"value="blue"></object> and movies/trailers of your game. Internally, Cinematics are implemented as <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">AppStates</a>.
JME3 cinematics (com.jme.cinematic) allow you to remote control nodes and cameras in a 3D game: You can script and and play cinematic scenes. You can use cinematics to create <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Cutscene"><paramname="text"value="<html><u>cutscenes</u></html>"><paramname="textColor"value="blue"></object> and movies/trailers for your game. Internally, Cinematics are implemented as <ahref="/com/jme3/gde/docs/jme3/advanced/application_states.html">AppStates</a>.
</p>
<p>
@ -19,12 +19,12 @@ This Node can be the rootNode, or a Node that is attached to the rootNode. </div
</li>
<li><div> Create a Cinematic object for this movie scene. The Cinematic will contain and manage the movie script.</div>
</li>
<li><div> For each line in your script (for each frame in your timeline), add a CinematicEvent to the Cinematic. </div>
<li><div> For each line in your script (for each keyframe in your timeline), add a CinematicEvent to the Cinematic. </div>
</li>
</ol>
</div>
<!-- EDIT1 SECTION "JME3 Cinematics" [1-956] -->
<!-- EDIT1 SECTION "JME3 Cinematics" [1-923] -->
<h2><a>Sample Code</a></h2>
<div>
<ul>
@ -33,7 +33,7 @@ This Node can be the rootNode, or a Node that is attached to the rootNode. </div
</ul>
</div>
<!-- EDIT2 SECTION "Sample Code" [957-1123] -->
<!-- EDIT2 SECTION "Sample Code" [924-1090] -->
<h2><a>How to Use a Cinematic</a></h2>
<div>
@ -42,9 +42,9 @@ This Node can be the rootNode, or a Node that is attached to the rootNode. </div
A Cinematic is like a movie script for a node.
</p>
<pre>Cinematic cinematic = new Cinematic(sceneNode, duration);
<li><div> Create one CinematicEvent for each line of your movie script. </div>
<ul>
<li><div><code>track</code> is one motion of a moving object. You can add several tracks. More details below.</div>
<li><div><code>event</code> is one motion of a moving object. You can add several events. More details below.</div>
</li>
<li><div><code>starttime</code> is the time when this particular cinematic event starts on the timeline. Specify the start time in seconds since the beginning of the cinematic.</div>
<td>MotionTrack</td><td>Use a MotionTrack to move a Spatial non-linearly over time. A MotionTrack is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases. </td>
<td>MotionEvent</td><td>Use a MotionEvent to move a Spatial non-linearly over time. A MotionEvent is based on a list of waypoints in a MotionPath. The curve goes through each waypoint, and you can adjust the tension of the curve to modify the roundedness of the path. This is the motion interpolation you are going to use in most cases. </td>
</tr>
<tr>
<td>PositionTrack</td><td>Use a PositionTrack to move a Spatial linearly over time. This linear interpolation results in straight motion segments between the way points. Use this to make the remote-controlled objects zig-zag from one way point to the other in a straight line.</td>
<td>SoundEvent</td><td>Use a SoundEvent to play a <ahref="/com/jme3/gde/docs/jme3/advanced/audio.html">sound</a> at a given time for the given duration.</td>
</tr>
<tr>
<td>RotationTrack</td><td>Use a RotationTrack to change the rotation of a Spatial over time. It spins the Spatial to the given angle in the given amount of time by linearly interpolating the rotation.</td>
<td>GuiEvent</td><td>Displays a <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> to the cinematic using <code>cinematic.bindUi("path/to/nifty/file.xml");</code></td>
</tr>
<tr>
<td>ScaleTrack</td><td>Use a ScaleTrack to change the size of a Spatial over time. It resizes the Spatial in the given amount of time by linearly interpolating the scale.</td>
</tr>
<tr>
<td>SoundTrack</td><td>Use a SoundTrack to play a <ahref="/com/jme3/gde/docs/jme3/advanced/audio.html">sound</a> at a given time for the given duration.</td>
</tr>
<tr>
<td>GuiTrack</td><td>Displays a <ahref="/com/jme3/gde/docs/jme3/advanced/nifty_gui.html">Nifty GUI</a> at a given time for the given duration. Use it to display subtitles or HUD elements. Bind the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> to the cinematic using <code>cinematic.bindUi("path/to/nifty/file.xml");</code></td>
</tr>
<tr>
<td>AnimationTrack</td><td>Use this to start playing a model <ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">animation</a> at a given time (a character walking animation for example)</td>
<td>AnimationEvent</td><td>Use this to start playing a model <ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">animation</a> at a given time (a character walking animation for example)</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [2723-4144] -->
<!-- EDIT6 TABLE [2688-3489] -->
<p>
The jMonkey team can add more types of tracks, just ask in the forum.
Of course one can make is own event implementation, by extending the AbstractCinematicEvent.
<td>track.setLoopMode(LoopMode.Loop)</td><td>Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).</td>
<td>event.setLoopMode(LoopMode.Loop)</td><td>Sets whether the animation along this path should loop (LoopMode.Loop) or play only once (LoopMode.DontLoop).</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.None)</td><td>Sets the direction behavior type of the controled node. Direction.None deactivates this feature. You can choose from the following options: LookAt, Path, PathAndRotation, Rotation.</td>
<td>event.setDirectionType(MotionEvent.Direction.None)</td><td>Sets the direction behavior type of the controlled node. Direction.None deactivates this feature. You can choose from the following options: LookAt, Path, PathAndRotation, Rotation.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.LookAt)</td><td>The spatial turns (rotates) to keep facing a certain point while moving. Specify the point with the <code>setLookAt()</code> method.</td>
<td>event.setDirectionType(MotionEvent.Direction.LookAt)</td><td>The spatial turns (rotates) to keep facing a certain point while moving. Specify the point with the <code>setLookAt()</code> method.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.Path)</td><td>The spatial always faces in the direction of the path while moving.</td>
<td>event.setDirectionType(MotionEvent.Direction.Path)</td><td>The spatial always faces in the direction of the path while moving.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.PathAndRotation)</td><td>The spatial faces the direction of the path, plus an added rotation. Use together with the <code>setRotation()</code> method.</td>
<td>event.setDirectionType(MotionEvent.Direction.PathAndRotation)</td><td>The spatial faces the direction of the path, plus an added rotation. Use together with the <code>setRotation()</code> method.</td>
</tr>
<tr>
<td>track.setDirectionType(MotionTrack.Direction.Rotation)</td><td>The spatial spins (rotates) while moving. You describe the spin by a custom quaternion. Use together with the <code>setRotation()</code> method.</td>
<td>event.setDirectionType(MotionEvent.Direction.Rotation)</td><td>The spatial spins (rotates) while moving. You describe the spin by a custom quaternion. Use together with the <code>setRotation()</code> method.</td>
</tr>
<tr>
<td>track.setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)</td><td>The spatial always faces towards this location. Use together with <code>MotionTrack.Direction.LookAt</code>.</td>
<td>event.setLookAt(teapot.getWorldTranslation(), Vector3f.UNIT_Y)</td><td>The spatial always faces towards this location. Use together with <code>MotionEvent.Direction.LookAt</code>.</td>
</tr>
<tr>
<td>track.setRotation(quaternion)</td><td>Sets the rotation. Use together with <code>MotionTrack.Direction.Rotation</code> or <code>MotionTrack.Direction.PathAndRotation</code>.</td>
<td>event.setRotation(quaternion)</td><td>Sets the rotation. Use together with <code>MotionEvent.Direction.Rotation</code> or <code>MotionEvent.Direction.PathAndRotation</code>.</td>
</tr>
</table></div>
<!-- EDIT8 TABLE [4701-6109] -->
<!-- EDIT8 TABLE [4069-5478] -->
<p>
<strong>Tip:</strong> Most likely you remote-control more than one object in your scene. Give the tracks and paths useful names such as <code>dragon_track</code>, <code>dragon_path</code>, <code>hero_track</code>, <code>hero_path</code>, etc.
<strong>Tip:</strong> Most likely you remote-control more than one object in your scene. Give the events and paths useful names such as <code>dragonEvent</code>, <code>dragonPath</code>, <code>heroEvent</code>, <code>heroPath</code>, etc.
</p>
</div>
<!-- EDIT7 SECTION "MotionTrack" [4219-6305] -->
<h3><a>PositionTrack</a></h3>
<!-- EDIT7 SECTION "MotionEvent" [3584-5673] -->
<h3><a>SoundEvent</a></h3>
<div>
<p>
A PositionTrack moves a Spatial in a straight line from its current position to the end position.
A SoundEventplays a sound as part of the cinematic.
<li><div><code>thingNode</code> is the Spatial to be moved.</div>
<li><div><code>audioPath</code> is the path to an audio file as String, e.g. "Sounds/mySound.wav".</div>
</li>
<li><div><code>endPosition</code>is the target location as Vector3f. </div>
<li><div><code>isStream</code>toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.</div>
</li>
<li><div><code>duration</code> is the time that it should take from start to end point.</div>
<li><div><code>duration</code> is the time that it should take to play.</div>
</li>
<li><div><code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
</li>
</ul>
<p>
The start location is always the current location of the Spatial.
You must use this together with bindUI() to specify the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> file that you want to load:
A ScaleTrack remote-controls whether a spatial grows or shrinks.
</p>
<pre>ScaleTrack thingScaleControl = new ScaleTrack(
<li><div><code>audioPath</code> is the path to an audio file as String, e.g. "Sounds/mySound.wav".</div>
<li><div><code>thingNode</code> is the Spatial whose animation you want to play.</div>
</li>
<li><div><code>isStream</code> toggles between streaming and buffering. Set to true to stream long audio file, set to false to play short buffered sounds.</div>
<li><div><code>animationName</code> the name of the animation stored in the animated model that you want to trigger, as a String.</div>
</li>
<li><div><code>duration</code> is the time that it should take to play.</div>
A GuiTrack shows or hide a NiftyGUI as part of a cinematic.
There is a built in system for camera switching in Cinematics. It based on CameraNode, and the cinematic just enable the given CameraNode control at a given time.
First you have to bind a camera to the cinematic with a unique name. You'll be provided with a CameraNode
You must use this together with bindUI() to specify the Nifty <acronymtitle="Graphical User Interface">GUI</acronym><acronymtitle="Extensible Markup Language">XML</acronym> file that you want to load:
An AnimationTrack triggers an animation as part of a cinematic.
then you can do whatever you want with this camera node : place it so that you have a the camera angle you'd like, attach it to a motion event to have some camera scrolling, attach control of your own that give it whatever behavior you'd like.
In the above example, I want it to be a top view of the scene looking at the world origin.
Then i just have to schedule its activation in the cinematic. I want it to get activated 3 seconds after the start of the cinematic so I just have to do
Details of the constructor:
</p>
<ul>
<li><div><code>thingNode</code> is the Spatial whose animation you want to play.</div>
</li>
<li><div><code>animationName</code> the name of the animation stored in the animated model that you want to trigger, as a String.</div>
</li>
<li><div><code>duration</code> is the time that it should take to play.</div>
</li>
<li><div><code>loopMode</code> can be LoopMode.Loop, LoopMode.DontLoop, LoopMode.Cycle.</div>
See also: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/cinematics-system-for-jme3/"><paramname="text"value="<html><u>Cinematics by Nehon</u></html>"><paramname="textColor"value="blue"></object>
@ -8,7 +8,7 @@ The term collision can be used to refer to <a href="/com/jme3/gde/docs/jme3/adva
</p>
<p>
Non-physical collision detection is interesting because it uses less computing resources than physical collision detection. The non-physical calculations are faster because they do not have any side effects such as pushing other objects or bumping off of them. Tasks such as <ahref="/com/jme3/gde/docs/jme3/advanced/mouse_picking.html">mouse picking</a> are easily implemented using using mathematical techniques such as ray casting and intersections. Experienced developers optimize their games by finding ways to simulate certain (otherwise expensive physical) interactions in a non-physical way.
Non-physical collision detection is interesting because it uses less computing resources than physical collision detection. The non-physical calculations are faster because they do not have any side effects such as pushing other objects or bumping off of them. Tasks such as <ahref="/com/jme3/gde/docs/jme3/advanced/mouse_picking.html">mouse picking</a> are easily implemented using mathematical techniques such as ray casting and intersections. Experienced developers optimize their games by finding ways to simulate certain (otherwise expensive physical) interactions in a non-physical way.
</p>
<p>
@ -16,7 +16,7 @@ Non-physical collision detection is interesting because it uses less computing r
</p>
</div>
<!-- EDIT1 SECTION "Collision and Intersection" [1-1438] -->
<!-- EDIT1 SECTION "Collision and Intersection" [1-1432] -->
<h2><a>Collidable</a></h2>
<div>
@ -48,7 +48,7 @@ Note that jME counts <em>all</em> collisions, this means a ray intersecting a bo
<td>getCollision(i) </td><td>Returns the CollisionResult at index i.</td>
</tr>
</table></div>
<!-- EDIT3 TABLE [2081-2409] -->
<!-- EDIT3 TABLE [2075-2403] -->
<p>
A CollisionResult object contains information about the second party of the collision event.
</p>
@ -75,9 +75,9 @@ A CollisionResult object contains information about the second party of the coll
<td>getTriangleIndex()</td><td>Returns the index of the triangle on the second party's mesh that was hit.</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [2503-3036] -->
<!-- EDIT4 TABLE [2497-3030] -->
</div>
<!-- EDIT2 SECTION "Collidable" [1439-3037] -->
<!-- EDIT2 SECTION "Collidable" [1433-3031] -->
<h3><a>Code Sample</a></h3>
<div>
@ -133,7 +133,7 @@ Knowing the distance of the collisions is useful for example when you intersect
Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code!
In this tutorial, we (re)create a very simple rectangular mesh, and we have a look at different ways of coloring it. A flat rectangle may not look useful because it's exactly the same as a <code>com.jme3.scene.shape.Quad</code>. We choose this simple example in order to show you how to build any shape out of triangles ??? without the distractions of more complex shapes.
</p>
<p>
<strong>Note:</strong> In this tutorial, we (re)create a very simple rectangular mesh (a quad), and we have a look at different ways of coloring it. Coding a custom quad may not be very useful because it's exactly the same as the built-in <code>com.jme3.scene.shape.Quad</code>. We chose a simple quad to teach you how to build any shape out of triangles, without the distractions of more complex shapes.
</p>
<ul>
<li><div> Full code sample: <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://jmonkeyengine.googlecode.com/svn/branches/stable-alpha4/engine/src/test/jme3test/model/shape/TestCustomMesh.java"><paramname="text"value="<html><u>TestCustomMesh.java</u></html>"><paramname="textColor"value="blue"></object></div>
@ -13,43 +17,68 @@ In this tutorial, we (re)create a very simple rectangular mesh, and we have a lo
Polygon meshes are made up of triangles. The corners of the triangles are vertices. So, when ever you create a new shape, you break it down into triangles.
Let's look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to create a cube mesh. You also need to know the 8 corner coordinates (vertices). The trick is that you have to specify the vertices in a certain order: Each triangle separately, counter-clockwise.
Sounds worse than it is ??? here is an example:
Polygon <ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">mesh</a>es are made up of triangles. The corners of the triangles are called vertices. When ever you create any new shape, you break it down into triangles.
</p>
<p>
<strong>Example:</strong> Let's look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to describe a cube mesh. Therefor you must provide the coordinates of the triangles' 8 corners (called vertices).
</p>
<p>
The important thing is that you have to specify the vertices of each triangle in the right order: Each triangle separately, counter-clockwise.
</p>
<p>
Sounds harder than it is ??? let's create a simple custom mesh, a quad.
Okay, we want to create a Quad. A quad has four vertices, and is made up of two triangles.
The base class for creating meshes is <code>com.jme3.scene.Mesh</code>.
In this tutorial we want to create a 3x3 Quad. The quad has four vertices, and is made up of two triangles. In our example, we decide that the bottom left corner is at 0/0/0 and the top right is at 3/3/0.
</p>
<pre>Mesh mesh = new Mesh();</pre>
<pre>0,3,0--3,3,0
| \ |
| \ |
| \ |
| \ |
| \|
0,0,0--3,0,0</pre>
</div>
<!-- EDIT3 SECTION "Creating a Quad Mesh" [1519-1864] -->
<h3><a>The Mesh Object</a></h3>
<div>
<p>
If you create your own Mesh-based class, replace <code>mesh</code> by <code>this</code> in the following examples:
The base class for creating meshes is <code>com.jme3.scene.Mesh</code>.
</p>
<pre>public class MyMesh extends Mesh {}</pre>
<pre>Mesh mesh = new Mesh();</pre>
<p>
Tip: If you create your own Mesh-based class (<code>public class MyMesh extends Mesh { }</code>), replace the variable <code>mesh</code> by <code>this</code> in the following examples.
</p>
</div>
<!-- EDIT3 SECTION "Creating a Quad Mesh" [1384-1766] -->
<h3><a>Vertices</a></h3>
<!-- EDIT4 SECTION "The Mesh Object" [1865-2157] -->
<h3><a>Vertex Coordinates</a></h3>
<div>
<p>
To define your own shape, determine its vertex positions in space. Store them in an array using com.jme3.math.Vector3f. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array <code>vertices[]</code>.
To define your own shape, determine the shape's <strong>vertex coordinates</strong> in 3D space. Store the list of corner positions in an <code>com.jme3.math.Vector3f</code> array. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array <code>vertices[]</code>.
</p>
<pre>Vector3f [] vertices = new Vector3f[4];
@ -59,12 +88,12 @@ vertices[2] = new Vector3f(0,3,0);
vertices[3] = new Vector3f(3,3,0);</pre>
Next, define the Quad's 2D texture coordinates for each vertex, in the same order: Bottom left, bottom right, top left, top right. We name this array <code>texCoord[]</code>
Next, we define the Quad's 2D <strong>texture coordinates</strong> for each vertex, in the same order as the vertices: Bottom left, bottom right, top left, top right. We name this Vector2f array <code>texCoord[]</code>
</p>
<pre>Vector2f[] texCoord = new Vector2f[4];
@ -73,17 +102,33 @@ texCoord[1] = new Vector2f(1,0);
texCoord[2] = new Vector2f(0,1);
texCoord[3] = new Vector2f(1,1);</pre>
<p>
This syntax means, when you apply a texture to this mesh, the texture will fill the quad from corner to corner at 100% percent size. Especially when you stitch together a larger mesh, you use this to tell the renderer whether, and how exactly, you want to cover the whole mesh. E.g. if you use .5f or 2f as texture coordinates instead of 1f, textures will be stretched or shrunk accordingly.
Next we turn the unrelated coordinates into triangles ??? We define the order in which the mesh is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. Note that you must specify the vertices counter-clockwise!
Next we turn these unrelated coordinates into <strong>triangles</strong>: We define the order in which each triangle is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. If the corners are identical, you can (and should!) reuse an index for several triangles.
</p>
<p>
Remember that you must specify the vertices counter-clockwise.
<li><div> The indices 0,1,2,3 stand for the four vertices that you specified for the quad in <code>vertices[]</code>.</div>
</li>
<li><div> The 2,0,1 triangle starts at top left, continues bottom left, and ends at bottom right.</div>
</li>
<li><div> The 1,3,2 triangle start at bottom right, continues top right, and ends at top left.</div>
@ -94,18 +139,28 @@ Next we turn the unrelated coordinates into triangles ??? We define the order in
| \ |
0--1\1</pre>
<p>
If the shape is more complex, it has more triangles, and therefor also more vertices/indices. Just continue expanding the list by adding groups of three indices for each triangle. (For example a three-triangle "house" shape has 5 vertices/indices and you'd specify three groups: <code>int [] indexes = { 2,0,1, 1,3,2, 2,3,4 };</code>.)
</p>
<p>
<p><div>If you get the order wrong (clockwise) for some of the triangles, then these triangles face backwards. If the <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a>'s material uses the default <code>FaceCullMode.Back</code> (see "face culling"), the broken triangles appear as holes in the rendered mesh. You need to identify and fix them in your code.
</div></p>
</p>
</div>
<!-- EDIT6 SECTION "Connecting the Dots" [2609-3204] -->
<!-- EDIT7 SECTION "Connecting the Dots" [3476-4947] -->
<h3><a>Setting the Mesh Buffer</a></h3>
<div>
<p>
The Mesh data is stored in a buffer.
You store the Mesh data in a buffer.
</p>
<ol>
<li><div> Using <code>com.jme3.util.BufferUtils</code>, we create three buffers for the three types of information we have:</div>
<ul>
<li><div> vertex positions,</div>
<li><div> vertex coordinates,</div>
</li>
<li><div> texture coordinates,</div>
</li>
@ -113,11 +168,11 @@ The Mesh data is stored in a buffer.
</li>
</ul>
</li>
<li><div> We assign the data to the appropriate type of buffer inside the mesh object. The three buffer types are taken from an enum in <code>com.jme3.scene.VertexBuffer.Type</code>.</div>
<li><div> We assign the data to the appropriate type of buffer inside the <code>Mesh</code> object. The three buffer types (<code>Position</code>, <code>TextCoord</code>, <code>Index</code>) are taken from an enum in <code>com.jme3.scene.VertexBuffer.Type</code>.</div>
</li>
<li><div> The third parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are 3 ints representing 3 vertices in a triangle.</div>
<li><div> The integer parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are 3 ints representing 3 vertices in a triangle.</div>
</li>
<li><div>In order for jMonkey to correctly show the mesh in the scene, it needs to know the bounds of our new mesh. This can easily be achieved by calling the updateBound() method on it.</div>
<li><div>To render the mesh in the scene, we need to pre-calculate the bounding volume of our new mesh: Call the <code>updateBound()</code> method on it.</div>
<!-- EDIT7 SECTION "Setting the Mesh Buffer" [3205-4320] -->
<!-- EDIT8 SECTION "Setting the Mesh Buffer" [4948-6071] -->
<h2><a>Using the Mesh in a Scene</a></h2>
<div>
<p>
We create a <code>com.jme3.scene.Geometry</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.
We create a <code>com.jme3.scene.Geometry</code> from our <code>mesh</code>, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.
</p>
<pre>Geometry geo = new Geometry("OurMesh", mesh);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
<pre>Geometry geo = new Geometry("OurMesh", mesh); // using our custom mesh object
<!-- EDIT8 SECTION "Using the Mesh in a Scene" [4321-4740] -->
<!-- EDIT9 SECTION "Using the Mesh in a Scene" [6072-6547] -->
<h2><a>Dynamic Meshes</a></h2>
<div>
<p>
If modifying a mesh dynamically in a way which would change the model's bounds then you need to call updateModelBound() on the Geometry object containing the mesh after calling updateBounds() on the mesh object. There is a warning on updateModelBounds about not usually needing to use it but that can be ignored in this special case.
If you are modifying a mesh dynamically in a way which changes the model's bounds, you need to update it:
</p>
<ol>
<li><div> Call <code>updateBounds()</code> on the mesh object, and then </div>
</li>
<li><div> call <code>updateModelBound()</code> on the Geometry object containing the mesh. </div>
</li>
</ol>
<p>
The updateModelBounds() method warns you about not usually needing to use it, but that can be ignored in this special case.
There are more vertex buffers in a Mesh than the three shown above. For an overview, see also <ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">mesh</a>.
Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient. You can use the same mesh <code>mesh</code> object that you defined above.
Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient. For this demo, you can use the same mesh <code>mesh</code> object that you defined above.
</p>
<pre>Geometry geo = new Geometry ("ColoredMesh", mesh);
<pre>Geometry geo = new Geometry ("ColoredMesh", mesh); // using the custom mesh
Material matVC = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
@ -209,10 +271,11 @@ You create a float array color buffer:
</ul>
<p>
Loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. <strong>Note that the color values in this example are arbitrarily chosen.</strong> It's just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you'd assign meaningful values for the color buffer depending on which color you want your mesh to have.
Loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. <strong>Note that the color values in this example are arbitrarily chosen.</strong> It's just a quick loop to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, see screenshot), without writing too much code. For your own mesh, you'd assign meaningful values for the color buffer depending on which color you want your mesh to have.
</p>
<pre>for(int i = 0; i < 4; i++){
<pre>// note: the red and green values are arbitray in this example
for(int i = 0; i < 4; i++){
// Red value (is increased by .2 on each next vertex here)
<h3><a>Example: Using Meshes With Lighting.j3md</a></h3>
<div>
<p>
The examples used the mesh together with the Unshaded.j3md material. If you want to use the Mesh with a Phong illuminated material (such as Lighting.j3md), the mesh needs to include information about its normals. (The Normals encode in which direction a mesh polygon is facing, which is important for calculating light and shadow.)
The previous examples used the mesh together with the <code>Unshaded.j3md</code> material. If you want to use the mesh with a Phong illuminated material (such as <code>Lighting.j3md</code>), the mesh must include information about its Normals. (Normal Vectors encode in which direction a mesh polygon is facing, which is important for calculating light and shadow!)
</p>
<pre>float[] normals = new float[12];
normals = new float[]{0,0,1, 0,0,1, 0,0,1, 0,0,1};
You need to specify as many normals as the polygon has vertices. For a flat quad, the four normals point in the same direction. In this case, the direction is the Z unit vector (0,0,1), this means our quad is facing the camera.
</p>
You need as many normals as the polygon has vertices. For a flat quad, they point all in the same direction. In this case, the direction is the Z unit vector (Vector3f.UNIT_Z), this means the quad is facing the camera.
<p>
If the mesh is more complex or rounded, calculate cross products of neighbouring vertices to identify normal vectors!
</p>
</div>
<!-- EDIT12 SECTION "Example: Shaded Mesh with Normals" [7392-8163] -->
<!-- EDIT13 SECTION "Example: Using Meshes With Lighting.j3md" [9362-10288] -->
<h3><a>Example: Point Mode</a></h3>
<div>
<p>
Alternatively, you can show the vertices as colored points instead of coloring the faces.
Additionally to coloring the faces as just described, you can hide the faces and show only the vertices as colored corner points.
</p>
<pre>Geometry coloredMesh = new Geometry ("ColoredMesh", cMesh);
This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad's faces are not rendered at all. This can be used for a special debugging or editing mode.
This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad's faces are not rendered at all in this mode. You can use this to visualize a special debugging or editing mode in your game.
</p>
</div>
<!-- EDIT13 SECTION "Example: Point Mode" [8164-8819] -->
<!-- EDIT14 SECTION "Example: Point Mode" [10289-11022] -->
<h2><a>Debugging Tip: Culling</a></h2>
<div>
<p>
By default, jME3 optimizes a mesh by culling (not drawing) its backfaces. It determines which side the front or backface of a mesh is by the order of the vertices: The frontface is the one where the vertices are specified counter-clockwise.
By default, jME3 optimizes a mesh by "backface culling", this means not drawing the inside. It determines the side of a triangle by the order of the vertices: The frontface is the face where the vertices are specified counter-clockwise.
</p>
<p>
This means for you that your custom mesh is invisible when seen from "behind" or from the inside. This may not be a problem, often this is even intended because it's faster. The player will not look at the inside of most things anyway. For example, if your custom mesh is a closed polyhedron, or a flat wallpaper-like object, then rendering the backfaces (the inside of the pillar, the back of the painting, etc) would indeed be a waste of resources.
This means for you that, by default, your custom mesh is invisible when seen from "behind" or from the inside. This may not be a problem, typically this is even intended, because it's faster. The player will not look at the inside of most things anyway. For example, if your custom mesh is a closed polyhedron, or a flat wallpaper-like object, then rendering the backfaces (the inside of the pillar, the back of the painting, etc) would indeed be a waste of resources.
</p>
<p>
In case however that your usecase requires the backfaces to be visible, you have two options:
In case however that your usecase requires the backfaces be visible, you have two options:
</p>
<ul>
<li><div> If you have a very simple scene, you can just deactivate backface culling for this one mesh's material. <br/>
<li><div> If you have a very simple scene, you can simply deactivate backface culling for this one mesh's material. <pre>mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);</pre>
</div>
</li>
<li><div>The recommended solution is to specify each triangle twice, the second time with the opposite order of vertices. The second, reversed triangle is a second frontface that replaces the culled backface. <br/>
<li><div>Another solution for truly double-sided meshes is to specify each triangle twice, the second time with the opposite order of vertices. The second (reversed) triangle is a second frontface that covers up the culled backface. <pre>int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 };</pre>
</div>
</li>
</ul>
<hr/>
<p>
See also:
See also: <ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a> ??? contains more info about how to debug custom meshes (that do not render as expected) by changing the default culling behaviour.
</p>
<ul>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">Spatial</a> ??? contains more info about how to debug custom meshes (that do not render as expected) by changing the default culling behaviour.</div>
</li>
<li><div><ahref="/com/jme3/gde/docs/jme3/advanced/mesh.html">Mesh</a> ??? more details about advanced Mesh properties</div>
After playing around with the terrain in jME3, soon comes the requirement of having larger explorable lands. Increasing the size of one TerrainQuad leads to more memory usage, while it will still be easy to reach the worlds boundaries. That???s why TerrainGrid was designed. It extends the TerraindQuad class and uses 4 HeightMaps (dark blue) as the four sub-quad. This means that a terrain of size 513 will use tiles of 257. Also an LRUCache is built into the terrain package, so surrounding tiles (green) can be pre-cached on a different thread, lowering the loading time. The quads are updated as the camera approaches the boundary of the light blue section.
</p>
</div>
<!-- EDIT4 SECTION "Motivation" [2426-3108] -->
<!-- EDIT4 SECTION "Motivation" [2426-3157] -->
<h2><a>Rationale</a></h2>
<div>
@ -84,7 +85,7 @@ There exist also two basic HeightMapGrid implementations:
</ul>
</div>
<!-- EDIT5 SECTION "Rationale" [3109-4319] -->
<!-- EDIT5 SECTION "Rationale" [3158-4368] -->
<h2><a>Usage</a></h2>
<div>
<ol>
@ -111,5 +112,5 @@ Further information about terrain and TerrainQuad can be found in the wiki at:
@ -234,7 +234,7 @@ JME3 uses some global uniforms for lighting :
</ul>
<p>
these uniforms are passed to the shader without having to declare them in the j3md file, but you have to specify in the technique definition " LightMode MultiPass" see lighting.j3md for more information.
These uniforms are passed to the shader without having to declare them in the j3md file, but you have to specify in the technique definition " LightMode MultiPass" see lighting.j3md for more information.
<br/>
@ -464,4 +464,4 @@ Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uni
@ -19,11 +19,11 @@ There are two ways how the camera can do that:
<p>
<strong>Important:</strong> Using third-person view requires you to deactivate the default flyCam (first-person view). This means that you have to configure your own navigation (<ahref="/com/jme3/gde/docs/jme3/advanced/input_handling.html">key inputs and analogListener</a>) that make your player character walk. For moving a physical player character, use <code>player.setWalkDirection()</code>, for a non-pysical character you can use <code>player.move()</code>.
<strong>Important:</strong> Using third-person view requires you to deactivate the default flyCam (first-person view). This means that you have to configure your own navigation (<ahref="/com/jme3/gde/docs/jme3/advanced/input_handling.html">key inputs and analogListener</a>) that make your player character walk. For moving a physical player character, use <code>player.setWalkDirection()</code>, for a non-physical character you can use <code>player.move()</code>.
</p>
</div>
<!-- EDIT1 SECTION "Making the Camera Follow a 3rd-Person Character" [1-989] -->
<!-- EDIT1 SECTION "Making the Camera Follow a 3rd-Person Character" [1-990] -->
<h2><a>Code Samples</a></h2>
<div>
@ -38,7 +38,7 @@ Press the WASD or arrow keys to move. Drag with the left mouse button to rotate.
</ul>
</div>
<!-- EDIT2 SECTION "Code Samples" [990-1371] -->
<!-- EDIT2 SECTION "Code Samples" [991-1372] -->
<h2><a>Camera Node</a></h2>
<div>
@ -76,7 +76,7 @@ Example: Use with <a href="/com/jme3/gde/docs/jme3/advanced/physics.html">Charac
The camera's transformation is copied over the spatial's transformation. Use with first-person flyCam.</td>
</tr>
</table></div>
<!-- EDIT4 TABLE [2445-2956] -->
<!-- EDIT4 TABLE [2446-2957] -->
<p>
<strong>Code sample:</strong>
@ -87,7 +87,7 @@ The camera's transformation is copied over the spatial's transformatio
</ul>
</div>
<!-- EDIT3 SECTION "Camera Node" [1372-3197] -->
<!-- EDIT3 SECTION "Camera Node" [1373-3198] -->
<h2><a>Chase Camera</a></h2>
<div>
@ -137,7 +137,7 @@ new KeyTrigger(KeyInput.KEY_SPACE))</td><td>Activate mutiple triggers for the ro
<td>setRotationSensitivity(5f)</td><td>How fast the camera rotates. Use values around <1.0f (all bigger values are ignored).</td>
</tr>
</table></div>
<!-- EDIT6 TABLE [3732-5144] -->
<!-- EDIT6 TABLE [3733-5145] -->
<p>
<strong>Code sample:</strong>
@ -148,7 +148,7 @@ new KeyTrigger(KeyInput.KEY_SPACE))</td><td>Activate mutiple triggers for the ro
</ul>
</div>
<!-- EDIT5 SECTION "Chase Camera" [3198-5387] -->
<!-- EDIT5 SECTION "Chase Camera" [3199-5388] -->
<h2><a>Which to Choose?</a></h2>
<div>
@ -171,7 +171,7 @@ What is the difference of the two code samples above?
<td>Drag-to-Rotate rotates the target and the camera. You always see the target from behind.</td><td>Drag-to-Rotate rotates only the camera. You can see the target from various sides.</td>
<td> Common/MatDefs/Misc/ShowNormals.j3md </td><td> A color gradient calculated from the model's surface normals. You can use this built-in material to debug the generation of normals in meshes, to preview models that have no material and no lights, or as fall-back default material. This built-in material has no parameters. </td>
</tr>
</table></div>
<!-- EDIT10 TABLE [10193-10564] -->
<!-- EDIT10 TABLE [10169-10540] -->
</div>
<!-- EDIT9 SECTION "Other: Test and Debug" [10160-10565] -->
<!-- EDIT9 SECTION "Other: Test and Debug" [10136-10541] -->
<td>getAdditionalRenderState().setBlendMode(BlendMode.PremultAlpha);</td><td>Pre-multiplied alpha blending. E.g. if the color of the object has already been multiplied by its alpha, this is used instead of "Alpha" blend mode.</td><td>For use with Premult Alpha textures.</td>
</tr>
</table></div>
<!-- EDIT13 TABLE [10616-13066] -->
<!-- EDIT13 TABLE [10592-13042] -->
<p>
If the DiffuseMap has an alpha channel, use:
@ -332,7 +332,7 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
@ -352,9 +352,9 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
<td>getAdditionalRenderState().setFaceCullMode(FaceCullMode.FrontAndBack)</td><td>Culls both backfaces and frontfaces.</td><td>Use this as an efficient way to make an object temporarily invisible, while keeping all its other in-game properties (such as node attachment, collision shapes, interactions, etc) active.</td>
</tr>
</table></div>
<!-- EDIT15 TABLE [13385-14527] -->
<!-- EDIT15 TABLE [13361-14503] -->
</div>
<!-- EDIT14 SECTION "Culling" [13366-14528] -->
<!-- EDIT14 SECTION "Culling" [13342-14504] -->
<h3><a>Miscellaneous</a></h3>
<div>
<div><table>
@ -368,7 +368,7 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
<td>getAdditionalRenderState().setPolyOffset();</td><td>Enable polygon offset.</td><td>Use this when you have meshes that have triangles really close to each over (e.g. <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Coplanarity"><paramname="text"value="<html><u>Coplanar</u></html>"><paramname="textColor"value="blue"></object>), it will shift the depth values to prevent <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://en.wikipedia.org/wiki/Z-fighting"><paramname="text"value="<html><u>Z-fighting</u></html>"><paramname="textColor"value="blue"></object>.</td>
</tr>
</table></div>
<!-- EDIT17 TABLE [14554-15320] -->
<!-- EDIT17 TABLE [14530-15296] -->
<p>
<strong>Related Links</strong>
@ -389,7 +389,7 @@ Later, put the Geometry (not the Material!) in the appropriate render queue
@ -12,16 +12,13 @@ All visible game elements in a scene, whether it is a Model or a Shape, are made
</p>
<ul>
<li><div> Meshes are made up of triangles. <br/>
<code>getTriangleCount(???)</code> and <code>getTriangle(???)</code></div>
<li><div> Meshes are made up of triangles: <code>getTriangleCount(???)</code> and <code>getTriangle(???)</code></div>
</li>
<li><div> Each mesh has a unique ID <br/>
<code>getId()</code></div>
<li><div> Each mesh has a unique ID: <code>getId()</code></div>
</li>
<li><div> Meshes have transformations: Location (local translation), rotation, scale.</div>
</li>
<li><div> Meshes have a bounding volume. jME3 can detect intersections (that is, non-physical collisions) between meshes, or between meshes and 2D elements such as rays. <br/>
<code>collideWith()</code>.</div>
<li><div> Meshes have a bounding volume. jME3 can detect intersections (that is, non-physical collisions) between meshes, or between meshes and 2D elements such as rays: <code>collideWith()</code>.</div>
</li>
<li><div> Meshes are locked with <code>setStatic()</code> and unlocked with <code>setDynamic()</code>. </div>
<ul>
@ -31,25 +28,35 @@ All visible game elements in a scene, whether it is a Model or a Shape, are made
</li>
</ul>
</li>
<li><div> (Optional) Meshes can have a LOD (level of detail optimization) that renders more or less details depending on distance from the camera.</div>
</li>
</ul>
<p>
You can use default <ahref="/com/jme3/gde/docs/jme3/advanced/shape.html">Shape</a>s as meshes; load<ahref="/com/jme3/gde/docs/jme3/advanced/3d_models.html">3D models</a> (i.e. meshes created in external applications); or create free-form <ahref="/com/jme3/gde/docs/jme3/advanced/custom_meshes.html">custom meshes</a> programmatically.
You have several options when<ahref="/com/jme3/gde/docs/jme3/advanced/spatial.html">creating Geometries from meshes</a>:
</p>
<ul>
<li><div> Use built-in <ahref="/com/jme3/gde/docs/jme3/advanced/shape.html">Shape</a>s as meshes; </div>
</li>
<li><div> Load <ahref="/com/jme3/gde/docs/jme3/advanced/3d_models.html">3D models</a> (that is, meshes created in external applications); or </div>
The VertexBuffer contains a particular type of geometry data used by Meshes. Every VertexBuffer set on a Mesh is sent as an attribute to the vertex shader to be processed.
Optionally, custom meshes can have a LOD (level of detail optimization) that renders more or less detail, depending on the distance of the mesh from the camera. You have to specify several vertex buffers, one for each level of detail you want (very far away with few details, close up with all details, and something in the middle). Use <code>setLodLevels(VertexBuffer[] lodLevels)</code>.
@ -82,7 +82,7 @@ The following <code>pick target</code> input mapping implements an action that d
</p>
<p>
<strong>Note:</strong> Picking with a visible pouse pointer implies that your application can no longer use the default flyCam where the MouseAxisTrigger rotates the camera. You have to deactivate the flyCam mappings and provide custom mappings. Either different inputs rotate the camera, or the camera is fixed.
<strong>Note:</strong> Picking with a visible mouse pointer implies that your application can no longer use the default flyCam where the MouseAxisTrigger rotates the camera. You have to deactivate the flyCam mappings and provide custom mappings. Either different inputs rotate the camera, or the camera is fixed.
</p>
<ol>
@ -147,4 +147,4 @@ The following example rotates Spatials named "Red Box" or "Blue B
</div>
<!-- EDIT3 SECTION "Pick a Target Using the Mouse Pointer" [3110-] -->
jME3 is similar to Swing in that for speed and efficiency all changes to the world must be made in a single update thread. This is happening automatically if using Controls and AppSates update metod or simpleUpdate however whenever you pass work to another thread you need to hand the results back to the main jME3 thread before making any changes to the scene graph.
</p>
<pre> public void rotateGeography(final Geography goe, final Quaternian rot) {
mainApp.enqueue(new Callable<Spatial>() {
public Spatial call() throws Exception {
return geo.rotate(rot);
}
});
}</pre>
<pre>public void rotateGeometry(final Geometry geo, final Quaternion rot){
public Spatial call() throws Exception {
return geo.rotate(rot);
}
});
}</pre>
<p>
Note that this example does not fetch the returned value by calling <code>get()</code> on the Future object returned from <code>enqueue()</code>. This means that the example method <code>rotateGeography()</code> will return immediately and will not wait for the rotation to be processed before continuing.
Note that this example does not fetch the returned value by calling <code>get()</code> on the Future object returned from <code>enqueue()</code>. This means that the example method <code>rotateGeometry()</code> will return immediately and will not wait for the rotation to be processed before continuing.
</p>
<p>
If the processing thread needs to wait or needs the return value then <code>get()</code> or the other methods in the returned Future object such as <code>isDone()</code> can be used.
</p>
</div>
<!-- EDIT1 SECTION "The jME3 Threading Model" [1-1133] -->
<!-- EDIT1 SECTION "The jME3 Threading Model" [1-1092] -->
<h1><a>Multithreading Optimization</a></h1>
<div>
@ -35,7 +34,7 @@ First, make sure you know what <a href="/com/jme3/gde/docs/jme3/advanced/applica
</p>
<p>
More complex games may feature complex mathematical operations or artificially intelligent calculations (such as path finding for several NPCs). If you make many time-intensive calls on the same thread (in the update loop), they will block one another, and thus slow down the game to a degree that makes it unplayable. If your game requires long running tasks, you should run them concurrently on separate threads, which speeds up the application considerably.
More complex games may feature complex mathematical operations or artificial intelligence calculations (such as path finding for several NPCs). If you make many time-intensive calls on the same thread (in the update loop), they will block one another, and thus slow down the game to a degree that makes it unplayable. If your game requires long running tasks, you should run them concurrently on separate threads, which speeds up the application considerably.
</p>
<p>
@ -47,7 +46,7 @@ Effectively, each for-loop in the main update loop might be a chance for multith
@ -323,7 +323,7 @@ Inside myCustomStyles.xml you define styles like this:
Learn more about how to create styles by looking at the <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Build_from_Source"><paramname="text"value="<html><u>Nifty GUI source code</u></html>"><paramname="textColor"value="blue"></object> for ???nifty-style-black???. Copy it as a template and change it to create your own style.
</p>
<hr/>
<hr/>
<p>
Learn more from the NiftyGUI page:
@ -346,4 +346,4 @@ Learn more from the NiftyGUI page:
</div>
<!-- EDIT14 SECTION "Design Your Own Styles" [9494-] -->
@ -225,7 +225,7 @@ The following effect textures are available by default from <code>test-data.jar<
Browse the full source code of all <objectclassid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><paramname="content"value="http://code.google.com/p/jmonkeyengine/source/browse/#svn%2Ftrunk%2Fengine%2Fsrc%2Ftest%2Fjme3test%2Feffect"><paramname="text"value="<html><u>effect examples</u></html>"><paramname="textColor"value="blue"></object> here.
</p>
<hr/>
<hr/>
<p>
@ -238,4 +238,4 @@ See also: <a href="/com/jme3/gde/docs/jme3/advanced/effects_overview.html">Effec
@ -21,23 +21,58 @@ If you are looking for info on how to respond to physics events such as collisio
<div>
<p>
jME3 has a complete, slightly adapted but fully wrapped Bullet <acronymtitle="Application Programming Interface">API</acronym> that uses normal jME math objects (Vector3f, Quaternion etc) as input/output data. All normal bullet objects like RigidBodies, Constraints (called "Joints" in jME3) and the various collision shapes are available, all mesh formats can be converted from jME to bullet.
</p>
Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate, the physics space will be stepped multiple times per frame to make up for the missing calculations. You create a Bullet PhysicsSpace in jME3 with a <code>com.jme3.bullet.BulletAppState</code>.
<p>
The PhysicsSpace object is the central object in bullet and all objects have to be added to it so they are physics-enabled. You can create multiple physics spaces as well to have multiple independent physics simulations or to run simulations in the background that you step at a different pace. You can also create a Bullet PhysicsSpace in jME3 with a <code>com.jme3.bullet.BulletAppState</code> which runs a PhysicsSpace along the update loop, which is the easiest way to instantiate a physics space. It can be run in a mode where it runs in parallel to rendering, yet syncs to the update loop so you can apply physics changes safely during the update() calls of Controls and SimpleApplication.
</p>
<p>
Internally, the updating and syncing of the actual physics objects happens in the following way:
The base bullet objects are also available as simple to use controls that can be attached to spatials to directly control these by physics forces and influences. The RigidBodyControl for example includes a simple constructor that automatically creates a hull collision shape or a mesh collision shape based on the given input mass and the mesh of the spatial it is attached to. This makes enabling physics on a Geometry as simple as "spatial.addControl(new RigidBodyControl(1));"
Due to some differences in how bullet and jME handle the scene and other objects relations there is some things to remember about the controls implementation:
</p>
<ul>
<li><div> The collision shape is not automatically updated when the spatial mesh changes</div>
<ul>
<li><div> You can update it by reattaching the control or by using the CollisionShapeFactory yourself.</div>
</li>
<li><div> user update (<code>simpleUpdate</code> in main loop, <code>update()</code> in Controls and AppStates)</div>
</ul>
</li>
<li><div> physics to scenegraph syncing and applying (<code>updateLogicalState()</code>)</div>
<li><div> In bullet the scale parameter is on the collision shape (which equals the mesh in jME3) and not on the RigidBody so you cannot scale a collision shape without scaling any other RigidBody with reference of it</div>
<ul>
<li><div> Note that you should share collision shapes in general and that j3o files loaded from file do that as well when instantiated twice so this is something to consider.</div>
</li>
<li><div> stepping physics (before or in parallel to <code>Application.render()</code>)</div>
</ul>
</li>
</ol>
<li><div><strong>Physics objects remain in the physics space when their spatials are detached from the scene graph!</strong></div>
<ul>
<li><div> Use PhysicsSpace.remove(physicsObject) or simply physicsControl.setEnabled(false); to remove them from the PhysicsSpace</div>
</li>
</ul>
</li>
<li><div> If you apply forces to the physics object in an update() call they might not get applied because internally bullet still runs at 60fps while your app might run at 120.</div>
<ul>
<li><div> You can use the PhysicsTickListener interface and register with the physics space and use the preTick() method to be sure that you actually apply the force in the right moment.</div>
</li>
<li><div> Reading values from the physics objects in the update loop should always yield correct values but they might not change over several fames due to the same reason.</div>
</li>
</ul>
</li>
<li><div> Reading or writing from the physics objects during the render phase is not recommended as this is when the physics space is stepped and would cause data corruption. This is why the debug display does not work properly in a threaded BulletAppState</div>
</li>
<li><div> Bullet always uses world coordinates, there is no such concept as nodes so the object will be moved into a world location with no regard to its parent spatial.</div>
<ul>
<li><div> You can configure this behavior using the setApplyPhysicsLocal() method on physics controls but remember the physics space still runs in world coordinates so you can visually detach things that will actually still collide in the physics space.</div>
</li>
<li><div> To use the local applying to simulate e.g. the internal physics system of a train passing by, simply create another BulletAppState and add all models with physics controls in local mode to a node. When you move the node the physics will happen all the same but the objects will move along with the node.</div>
</li>
</ul>
</li>
</ul>
<p>
@ -52,8 +87,27 @@ When you use this physics simulation, values correspond to the following units:
</li>
</ul>
<p>
Bullet physics runs internally at 60fps by default. This rate is not dependent on the actual framerate and it does not lock the framerate at 60fps. Instead, when the actual fps is higher than the physics framerate the system will display interpolated positions for the physics objects. When the framerate is lower than the physics framerate, the physics space will be stepped multiple times per frame to make up for the missing calculations.
</p>
<p>
Internally, the updating and syncing of the actual physics objects in the BulletAppState happens in the following way:
@ -173,7 +227,7 @@ Disc-shaped objects like wheels, plates. </td>
<td> PlaneCollisionShape() </td><td> A 2D plane. Very fast. </td><td> Flat solid floor or wall. </td>
</tr>
</table></div>
<!-- EDIT6 TABLE [4304-5701] -->
<!-- EDIT6 TABLE [8201-9598] -->
<p>
All non-mesh CollisionShapes can be used for dynamic, kinematic, as well as static Spatials. (Code samples see below)
@ -200,7 +254,7 @@ All non-mesh CollisionShapes can be used for dynamic, kinematic, as well as stat
<strong>Limitations:</strong> Requires heightmap data. Collisions between two mesh-accurate shapes cannot be detected, only non-mesh shapes can collide with this shape.</td><td>Static terrains.</td>
</tr>
</table></div>
<!-- EDIT7 TABLE [5822-7339] -->
<!-- EDIT7 TABLE [9719-11236] -->
<p>
On a CollisionShape, you can apply a few properties
@ -214,7 +268,7 @@ On a CollisionShape, you can apply a few properties
<code>new Vector3f(1f,2f,1f)</code></td>
</tr>
</table></div>
<!-- EDIT8 TABLE [7393-7930] -->
<!-- EDIT8 TABLE [11290-11827] -->
<p>
The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code samples see below).
@ -231,7 +285,7 @@ The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code sa
</p>
</div>
<!-- EDIT5 SECTION "Create a CollisionShape" [3846-8600] -->
<!-- EDIT5 SECTION "Create a CollisionShape" [7743-12497] -->
<h3><a>CollisionShape Code Samples</a></h3>
<div>
<ul>
@ -262,7 +316,7 @@ The mesh-accurate shapes can use a CollisionShapeFactory as constructor (code sa
<td>GhostControl</td><td>Use for collision and intersection detection between physical objects. A GhostControl itself is <em>non-solid</em> and invisible. GhostControl moves with the Spatial it is attached to. Use GhostControls to <ahref="/com/jme3/gde/docs/jme3/advanced/physics_listeners.html">implement custom game interactions</a> by adding it to a visible Geometry. </td><td>A monster's "aggro radius", CharacterControl collisions, motion detectors, photo-electric alarm sensors, poisonous or radioactive perimeters, life-draining ghosts, etc. </td>
@ -298,14 +352,14 @@ PhysicsVehicleWheel</td><td> Special Control used for <a href="/com/jme3/gde/doc
<td>RagDollControl</td><td>Special Control used for <ahref="/com/jme3/gde/docs/jme3/advanced/ragdoll.html">collapsing, flailing, or falling characters</a></td><td>Falling persons, animals, robots, "Rag dolls"</td>
</tr>
</table></div>
<!-- EDIT12 TABLE [11100-11612] -->
<!-- EDIT12 TABLE [14997-15509] -->
<p>
Click the links for details on the special PhysicsControls. This article is about RigidBodyControl.
<!-- EDIT15 SECTION "Add PhysicsControl to PhysicsSpace" [13543-14358] -->
<!-- EDIT15 SECTION "Add PhysicsControl to PhysicsSpace" [17440-18255] -->
<h2><a>Changing the Scale of a PhysicsControl</a></h2>
<div>
@ -427,7 +481,7 @@ With the corresponding output below:
</p>
</div>
<!-- EDIT16 SECTION "Changing the Scale of a PhysicsControl" [14359-16109] -->
<!-- EDIT16 SECTION "Changing the Scale of a PhysicsControl" [18256-20006] -->
<h3><a>PhysicsSpace Code Samples</a></h3>
<div>
@ -457,9 +511,9 @@ setWorldMin(new Vector3f(-10000f, -10000f, -10000f));</td><td>Specifies the size
<td>setCcdMotionThreshold()</td><td>The amount of motion in 1 physics tick to trigger the continuous motion detection in moving objects that push one another. Rarely used, but necessary if your moving objects get stuck or roll through one another.</td>
<!-- EDIT22 SECTION "Kinematic vs Dynamic vs Static" [19961-22362] -->
<!-- EDIT22 SECTION "Kinematic vs Dynamic vs Static" [23858-26259] -->
<h2><a>Forces: Moving Dynamic Objects</a></h2>
<div>
@ -633,7 +687,7 @@ Use the following methods to move dynamic physical objects.
<td> clearForces()</td><td>Cancels out all forces (force, torque) etc and stops the motion.</td>
</tr>
</table></div>
<!-- EDIT25 TABLE [22468-23457] -->
<!-- EDIT25 TABLE [26365-27354] -->
<p>
<p><div>It is technically possible to position PhysicsControls using setLocalTranslation(), e.g. to place them in their start position in the scene. However you must be very careful not to cause an "impossible state" where one physical object overlaps with another! Within the game, you typically use the setters shown here exclusively.
@ -667,13 +721,13 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
<td> setSleepingThreshold(float,float)</td><td>Sets the sleeping thresholds which define when the object gets deactivated to save resources. The first value is the linear threshold and the second the angular. Low values keep the object active when it barely moves (slow precise performance), high values put the object to sleep immediately (imprecise fast performance). (?) </td>
</tr>
<tr>
<td> setCcdMotionThreshold(0f) </td><td>Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection in movign obejcts that push one another. This avoids the problem of fast objects moving through other objects. Set to zero to disable (default).</td>
<td> setCcdMotionThreshold(0f) </td><td>Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection in moving objects that push one another. This avoids the problem of fast objects moving through other objects. Set to zero to disable (default).</td>
</tr>
<tr>
<td> setCcdSweptSphereRadius(.5f)</td><td>Bullet does not use the full collision shape for continuous collision detection, instead it uses a "swept sphere" shape to approximate a motion, which can be imprecise and cause strange behaviours such as objects passign through one another or getting stuck. Only relevant for fast moving dynamic bodies. </td>
<td> setCcdSweptSphereRadius(.5f)</td><td>Bullet does not use the full collision shape for continuous collision detection, instead it uses a "swept sphere" shape to approximate a motion, which can be imprecise and cause strange behaviors such as objects passing through one another or getting stuck. Only relevant for fast moving dynamic bodies. </td>
</tr>
</table></div>
<!-- EDIT26 TABLE [23875-25831] -->
<!-- EDIT26 TABLE [27772-29727] -->
<p>
<p><div> You can <code>setApplyPhysicsLocal(true)</code> for an object to make it move relatively to its local physics space. You would do that if you need a physics space that moves with a node (e.g. a spaceship with artificial gravity surrounded by zero-g space). By default, it's set to false, and all movement is relative to the world.
@ -681,7 +735,7 @@ removeCollideWithGroup(COLLISION_GROUP_01)</td><td>Collision Groups are integer
@ -167,7 +167,7 @@ To make a custom class savable:
<p>
<p><div>As with all serialization, remember that if you ever change data types in custom classes, the updated read() methods will no longer be able to read your old files.
<p><div>As with all serialization, remember that if you ever change data types in custom classes, the updated read() methods will no longer be able to read your old files. Also there has to be a constructor that takes no Parameters.
</div></p>
</p>
<div><span>
@ -190,4 +190,4 @@ To make a custom class savable:
@ -89,20 +89,21 @@ The polygon <a href="/com/jme3/gde/docs/jme3/advanced/mesh.html">Mesh</a> inside
<p>
Cloned spatials share the same mesh, while each cloned spatial can have its own local transformation (translation, rotation, and scale) in the scene. This means you only use <code>clone()</code> on spatials whose meshes never change. The most common use case for cloning is when you use several Spatials that are based on the same <ahref="/com/jme3/gde/docs/jme3/advanced/shape.html">Shape</a>s.
Cloned spatials share the same mesh, while each cloned spatial can have its own local transformation (translation, rotation, and scale) in the scene. This means you only use <code>clone()</code> on spatials whose meshes never change. The most common use case for cloning is when you use several Spatials that are based on the same <ahref="/com/jme3/gde/docs/jme3/advanced/shape.html">Shape</a>s (e.g. trees, crates).
</p>
<p>
The second use case is: When you load a model using <code>loadModel()</code> from the AssetManager, you may get a <code>clone()</code>ed object. In particular:
The second use case is: When you load a model using <code>loadModel()</code> from the AssetManager, you may automatically get a <code>clone()</code>ed object. In particular:
</p>
<ul>
<li><div> If the model is not animated (it has no <code><ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">AnimControl</a></code>), you get a clone. All clones share one mesh object. (Uses less memory)</div>
<li><div> If the model is not animated (it has no <code><ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">AnimControl</a></code>), jME loads a clone. All clones share one mesh object in order to use less memory.</div>
</li>
<li><div> If the model is animated (it has a <code><ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">AnimControl</a></code>), then <code>loadModel()</code> duplicates the mesh for each loaded instance. (Uses more memory)</div>
<li><div> If the model is animated (it has a <code><ahref="/com/jme3/gde/docs/jme3/advanced/animation.html">AnimControl</a></code>), then <code>loadModel()</code> duplicates the mesh for each loaded instance. (Uses more memory, but can animate.)</div>
</li>
</ul>
<p>
Usually there is no need to manually use any of the <code>clone()</code> methods on models. Using the <ahref="/com/jme3/gde/docs/jme3/advanced/asset_manager.html">Asset Manager</a>'s <code>loadModel()</code> method will automatically do the right thing for your models.
</p>
@ -112,7 +113,7 @@ Usually there is no need to manually use any of the <code>clone()</code> methods
</p>
</div>
<!-- EDIT5 SECTION "What is a Clone?" [3729-4984] -->
<!-- EDIT5 SECTION "What is a Clone?" [3729-5049] -->
<h2><a>How to Add Fields and Methods to a Spatial</a></h2>
<div>
@ -127,15 +128,15 @@ You can include custom user data ???that is, custom Java objects and methods???
</p>
<p>
This first example adds an integer field named <code>health</code> to the Spatial <code>player_node</code>, and initializes it to 100.
This first example adds an integer field named <code>health</code> to the Spatial <code>playerNode</code>, and initializes it to 100.
The second example adds a set of custom accessor methods to the player object. You create a <ahref="/com/jme3/gde/docs/jme3/advanced/custom_controls.html">custom PlayerControl() class</a> and you add this control to the Spatial:
In your PlayerControl() class, you define custom methods that set and get your user data in the <code>spatial</code> object. For example, the control could add accessors that set and get the player's health:
@ -148,11 +149,11 @@ public void setHealth(int h) {
}</pre>
<p>
Elsewhere in your code, you can access this data wherever you have access to the Spatial <code>player_node</code>.
Elsewhere in your code, you can access this data wherever you have access to the Spatial <code>playerNode</code>.
<li><div> You can add as many data objects (of String, Boolean, Integer, Float, Array types) to a Spatial as you want. Just make sure to label them with unique case-sensitive strings (<code>health</code>, <code>Inventory</code>, <code>equipment</code>, etc). </div>
</li>
@ -171,7 +172,7 @@ This is how you list all data keys that are already defined for one Spatial:
}</pre>
</div>
<!-- EDIT6 SECTION "How to Add Fields and Methods to a Spatial" [4985-7561] -->
<!-- EDIT6 SECTION "How to Add Fields and Methods to a Spatial" [5050-7620] -->
<h2><a>How to Access a Named Sub-Mesh</a></h2>
<div>
@ -196,7 +197,7 @@ In the following example, the Node <code>house</code> is the loaded model. The s
<!-- EDIT7 SECTION "How to Access a Named Sub-Mesh" [7562-8364] -->
<!-- EDIT7 SECTION "How to Access a Named Sub-Mesh" [7621-8423] -->
<h2><a>What is Culling?</a></h2>
<div>
@ -205,18 +206,22 @@ There are two types of culling: Face culling, and view frustrum culling.
</p>
<p>
<strong>Face culling</strong> refers to not drawing certain polygons of a mesh. The "inside" of the mesh (the so called backface) is never visible to the player, and as an optimization, game engines skip calculating backfaces by default. You may want to deactivate Face Culling while debugging custom meshes, so you can see them in case you turned them inside-out by accident.
<strong>Face culling</strong> means not drawing certain polygons of a mesh. Face culling behaviour is a property of the material.
</p>
<p>
Usage: The "inside" of a mesh (the so called backface) is typically never visible to the player, and as an optimization, the <code>Back</code> mode skips calculating all backfaces by default. Activating the <code>Off</code> or <code>Front</code> modes can be useful when you are debugging <ahref="/com/jme3/gde/docs/jme3/advanced/custom_meshes.html">custom meshes</a> and try to identify accidental inside-out faces.
</p>
<p>
You can switch the com.jme3.material.RenderState.FaceCullMode to
You can switch the com.jme3.material.RenderState.FaceCullMode to either:
</p>
<ul>
<li><div><code>FaceCullMode.Back</code> (default) ??? only the frontsides of a mesh are drawn. This is the normal behaviour. </div>
<li><div><code>FaceCullMode.Back</code> (default) ??? Only the frontsides of a mesh are drawn. Backface culling is the default behaviour. </div>
</li>
<li><div><code>FaceCullMode.Front</code> ??? only the backsides of meshes are drawn. The mesh will probably turn invisible. Useful if you are debugging a hand-made mesh and try to identify accidental inside-out faces.</div>
<li><div><code>FaceCullMode.Front</code> ??? Only the backsides of a mesh are drawn. A mesh with frontface culling will most likely be invisible. Used for debugging "inside-out" custom meshes.</div>
</li>
<li><div><code>FaceCullMode.FrontAndBack</code> ??? The mesh becomes invisible. </div>
<li><div><code>FaceCullMode.FrontAndBack</code> ??? Use this to make a mesh temporarily invisible. </div>
</li>
<li><div><code>FaceCullMode.Off</code> ??? Every side of the mesh is drawn. Looks normal, but slows down large scenes.</div>
You attach the <code>terrain</code> and the first-person <code>player</code> to the rootNode, and to the physics space, to make them appear in the game world.
@ -290,7 +282,7 @@ You attach the <code>terrain</code> and the first-person <code>player</code> to
<!-- EDIT6 SECTION "Combining the Two" [10183-11031] -->
<!-- EDIT6 SECTION "Combining the Two" [10008-10557] -->
<h2><a>Conclusion</a></h2>
<div>
@ -302,7 +294,7 @@ You see that you can combine snippets of sample code (such as HelloTerrain and H
<p>
You should spawn high up in the area and fall down to the map, giving you a few seconds to survey the area. Then walk around and see how you like the lay of the land.