- update help sets - add missing help pages to wiki_help.properties git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9075 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
@ -1,3 +1,84 @@ |
|||||||
<h1><a>Models and Scenes</a></h1><div><p>Like <a href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s, 3D models are also made up of <a href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a>es, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors.</p></div><h2><a>Using Models and Scenes with jME3</a></h2><div><p>To use 3D models in a jME3 application:</p><ol><li><div>Export the 3D model in Ogre <acronym title="Extensible Markup Language">XML</acronym> or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div></li><li><div>Save the files into a subdirectory of your jME3 project's <code>assets</code> directory.</div></li><li><div>In your code, you use the <a href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models as <a href="/com/jme3/gde/core/docs/jme3/advanced/spatial.html">Spatial</a>s into a jME application.<pre>Spatial model = assetManager.loadModel( |
|
||||||
"Models/MonkeyHead/MonkeyHead.mesh.xml" );</pre></div></li><li><div>(For the release build:) Use the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> to convert models to .j3o format. You don't need this step as long you still develop and test the aplication within the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>.</div></li></ol></div><h2><a>Creating Models and Scenes</a></h2><div><p>To create 3D models and scenes, you need a 3D Mesh Editor such as <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.blender.org/"><param name="text" value="<html><u>Blender</u></html>"><param name="textColor" value="blue"></object>, with an OgreXML Exporter plugin.</p><p><strong>Tip:</strong> Consider creating <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/UV_Map_Basics"><param name="text" value="<html><u>UV textures</u></html>"><param name="textColor" value="blue"></object> for more complex models, it looks more professional.</p><p>3D mesh editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users:</p><p>To export your models as Ogre <acronym title="Extensible Markup Language">XML</acronym> meshes with materials:</p><ol><li><div>Open the menu File > Export > OgreXML Exporter to open the exporter dialog.</div></li><li><div>In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some <acronym title="Joint Photographics Experts Group">JPG</acronym> files.</div></li><li><div>In the Export Meshes field: Select a target subdirectory of your <code>assets/Models/</code> directory. E.g. <code>assets/Models/something/</code>.</div></li><li><div>Activate the following exporter settings:</div><ul><li><div>Copy Textures: YES</div></li><li><div>Rendering Materials: YES</div></li><li><div>Flip Axis: YES</div></li><li><div>Require Materials: YES</div></li><li><div>Skeleton name follows mesh: YES</div></li></ul></li><li><div>Click export.</div></li></ol><p>You can now use the <a href="/com/jme3/gde/core/docs/sdk.html">jMonkeyEngine SDK</a> to <a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">load and view models</a>. You can <a href="/com/jme3/gde/core/docs/sdk/scene_composer.html">create scenes</a> from them and write cde that loads them into your application.</p></div> |
<h1><a>Models and Scenes</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Like <a href="/com/jme3/gde/core/docs/jme3/advanced/shape.html">Shape</a>s, 3D models are also made up of <a href="/com/jme3/gde/core/docs/jme3/advanced/mesh.html">Mesh</a>es, but models are more complex than Shapes. While Shapes are built into jME3, you typically create models in external 3D Mesh Editors. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Using Models and Scenes with jME3</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
To use 3D models in a jME3 application: |
||||||
|
</p> |
||||||
|
<ol> |
||||||
|
<li><div> Export the 3D model in Ogre <acronym title="Extensible Markup Language">XML</acronym> or Wavefront OBJ format. Export Scenes as Ogre DotScene format.</div> |
||||||
|
</li> |
||||||
|
<li><div> Save the files into a subdirectory of your jME3 project's <code>assets</code> directory.</div> |
||||||
|
</li> |
||||||
|
<li><div> In your code, you use the <a href="/com/jme3/gde/core/docs/jme3/advanced/asset_manager.html">Asset Manager</a> to load models as <a href="/com/jme3/gde/core/docs/jme3/advanced/spatial.html">Spatial</a>s into a jME application. <pre>Spatial model = assetManager.loadModel( |
||||||
|
"Models/MonkeyHead/MonkeyHead.mesh.xml" );</pre> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li><div> (For the release build:) Use the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> to convert models to .j3o format. You don't need this step as long you still develop and test the aplication within the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>.</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Creating Models and Scenes</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
To create 3D models and scenes, you need a 3D Mesh Editor such as <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.blender.org/"><param name="text" value="<html><u>Blender</u></html>"><param name="textColor" value="blue"></object>, with an OgreXML Exporter plugin. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<strong>Tip:</strong> Consider creating <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/UV_Map_Basics"><param name="text" value="<html><u>UV textures</u></html>"><param name="textColor" value="blue"></object> for more complex models, it looks more professional. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
3D mesh editors are third-party products, so please consult their documentation for instructions how to use them. Here is an example workflow for Blender users: |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
To export your models as Ogre <acronym title="Extensible Markup Language">XML</acronym> meshes with materials: |
||||||
|
</p> |
||||||
|
<ol> |
||||||
|
<li><div> Open the menu File > Export > OgreXML Exporter to open the exporter dialog.</div> |
||||||
|
</li> |
||||||
|
<li><div> In the Export Materials field: Give the material the same name as the model. For example, the model <code>something.mesh.xml</code> goes with <code>something.material</code>, plus (optionally) <code>something.skeleton.xml</code>, and some <acronym title="Joint Photographics Experts Group">JPG</acronym> files.</div> |
||||||
|
</li> |
||||||
|
<li><div> In the Export Meshes field: Select a target subdirectory of your <code>assets/Models/</code> directory. E.g. <code>assets/Models/something/</code>.</div> |
||||||
|
</li> |
||||||
|
<li><div> Activate the following exporter settings: </div> |
||||||
|
<ul> |
||||||
|
<li><div> Copy Textures: YES</div> |
||||||
|
</li> |
||||||
|
<li><div> Rendering Materials: YES</div> |
||||||
|
</li> |
||||||
|
<li><div> Flip Axis: YES</div> |
||||||
|
</li> |
||||||
|
<li><div> Require Materials: YES</div> |
||||||
|
</li> |
||||||
|
<li><div> Skeleton name follows mesh: YES</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li><div> Click export.</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
You can now use the <a href="/com/jme3/gde/core/docs/sdk.html">jMonkeyEngine SDK</a> to <a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">load and view models</a>. You can <a href="/com/jme3/gde/core/docs/sdk/scene_composer.html">create scenes</a> from them and write cde that loads them into your application. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:3d_models?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:3d_models?do=export_xhtmlbody">view online version</a></em></p> |
@ -0,0 +1,381 @@ |
|||||||
|
|
||||||
|
<h1><a>Simple AppStates Demo</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<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. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Main.java</a></h2> |
||||||
|
<div> |
||||||
|
<pre>package chapter04.appstatedemo; |
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.input.controls.KeyTrigger; |
||||||
|
import com.jme3.input.controls.Trigger; |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* This demo shows a simple "game" with three AppStates. Instead of game content, |
||||||
|
* it just displays three cubes on different backgrounds. |
||||||
|
* <ul> |
||||||
|
* <li>StartScreenState: This state is enabled |
||||||
|
* when the user starts the application, or the the game is paused. |
||||||
|
* Press BACKSPACE to return to the game, press RETURN to go to Settings.</li> |
||||||
|
* <li>GameRunningState: This state shows the game content and is enabled while the game is running. |
||||||
|
* Press BACKSPACE to pause and return to the start screen.</li> |
||||||
|
* <li>SettingsScreenState: This Settings screen state can be reached from the start screen |
||||||
|
* Press RETURN to toggle it on and off.</li> |
||||||
|
* </ul> |
||||||
|
*/</span> |
||||||
|
public class Main extends SimpleApplication { |
||||||
|
|
||||||
|
private Trigger pause_trigger = new KeyTrigger(KeyInput.KEY_BACK); |
||||||
|
private Trigger save_trigger = new KeyTrigger(KeyInput.KEY_RETURN); |
||||||
|
private boolean isRunning = false; // starts at startscreen |
||||||
|
private GameRunningState gameRunningState; |
||||||
|
private StartScreenState startScreenState; |
||||||
|
private SettingsScreenState settingsScreenState; |
||||||
|
|
||||||
|
|
||||||
|
/** Start the jMonkeyEngine application */ |
||||||
|
public static void main(String[] args) { |
||||||
|
Main app = new Main(); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* initialize the scene here |
||||||
|
*/</span> |
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
setDisplayFps(false); |
||||||
|
setDisplayStatView(false); |
||||||
|
|
||||||
|
gameRunningState = new GameRunningState(this); |
||||||
|
startScreenState = new StartScreenState(this); |
||||||
|
settingsScreenState = new SettingsScreenState(this); |
||||||
|
|
||||||
|
stateManager.attach(startScreenState); |
||||||
|
|
||||||
|
inputManager.addMapping("Game Pause Unpause", pause_trigger); |
||||||
|
inputManager.addListener(actionListener, new String[]{"Game Pause Unpause"}); |
||||||
|
inputManager.addMapping("Toggle Settings", save_trigger); |
||||||
|
inputManager.addListener(actionListener, new String[]{"Toggle Settings"}); |
||||||
|
} |
||||||
|
|
||||||
|
private ActionListener() { |
||||||
|
public void onAction(String name, boolean isPressed, float tpf) { |
||||||
|
System.out.println("key" + name); |
||||||
|
if (name.equals("Game Pause Unpause") && !isPressed) { |
||||||
|
if (isRunning) { |
||||||
|
stateManager.detach(gameRunningState); |
||||||
|
stateManager.attach(startScreenState); |
||||||
|
System.out.println("switching to startscreen..."); |
||||||
|
|
||||||
|
} else { |
||||||
|
stateManager.detach(startScreenState); |
||||||
|
stateManager.attach(gameRunningState); |
||||||
|
System.out.println("switching to game..."); |
||||||
|
} |
||||||
|
isRunning = !isRunning; |
||||||
|
} else if (name.equals("Toggle Settings") && !isPressed && !isRunning) { |
||||||
|
if (!isRunning && stateManager.hasState(startScreenState)) { |
||||||
|
stateManager.detach(startScreenState); |
||||||
|
stateManager.attach(settingsScreenState); |
||||||
|
System.out.println("switching to settings..."); |
||||||
|
} else if (!isRunning && stateManager.hasState(settingsScreenState)) { |
||||||
|
stateManager.detach(settingsScreenState); |
||||||
|
stateManager.attach(startScreenState); |
||||||
|
System.out.println("switching to startscreen..."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) {} |
||||||
|
|
||||||
|
} |
||||||
|
</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>GameRunningState.java</a></h2> |
||||||
|
<div> |
||||||
|
<pre>package chapter04.appstatedemo; |
||||||
|
|
||||||
|
import com.jme3.app.Application; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.app.state.AbstractAppState; |
||||||
|
import com.jme3.app.state.AppStateManager; |
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.font.BitmapFont; |
||||||
|
import com.jme3.font.BitmapText; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* A template how to create an Application State. This example state simply |
||||||
|
* changes the background color depending on the camera position. |
||||||
|
*/</span> |
||||||
|
public class GameRunningState extends AbstractAppState { |
||||||
|
|
||||||
|
private ViewPort viewPort; |
||||||
|
private Node rootNode; |
||||||
|
private Node guiNode; |
||||||
|
private AssetManager assetManager; |
||||||
|
private Node localRootNode = new Node("Game Screen RootNode"); |
||||||
|
private Node localGuiNode = new Node("Game Screen GuiNode"); |
||||||
|
private final ColorRGBA backgroundColor = ColorRGBA.Blue; |
||||||
|
|
||||||
|
public GameRunningState(SimpleApplication app){ |
||||||
|
this.rootNode = app.getRootNode(); |
||||||
|
this.viewPort = app.getViewPort(); |
||||||
|
this.guiNode = app.getGuiNode(); |
||||||
|
this.assetManager = app.getAssetManager(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
|
||||||
|
/** Load this scene */ |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
|
||||||
|
Box(Vector3f.ZERO, 1, 1, 1); |
||||||
|
Geometry geom = new Geometry("Box", mesh); |
||||||
|
Material mat = new Material(assetManager, |
||||||
|
"Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat.setColor("Color", ColorRGBA.Green); |
||||||
|
geom.setMaterial(mat); |
||||||
|
geom.setLocalTranslation(1, 0, 0); |
||||||
|
localRootNode.attachChild(geom); |
||||||
|
|
||||||
|
/** Load the HUD*/ |
||||||
|
BitmapFont guiFont = assetManager.loadFont( |
||||||
|
"Interface/Fonts/Default.fnt"); |
||||||
|
BitmapText displaytext = new BitmapText(guiFont); |
||||||
|
displaytext.setSize(guiFont.getCharSet().getRenderedSize()); |
||||||
|
displaytext.move(10, displaytext.getLineHeight() + 20, 0); |
||||||
|
displaytext.setText("Game running. Press BACKSPACE to pause and return to the start screen."); |
||||||
|
localGuiNode.attachChild(displaytext); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
/** the action happens here */ |
||||||
|
Vector3f v = viewPort.getCamera().getLocation(); |
||||||
|
viewPort.setBackgroundColor(new ColorRGBA(v.getX() / 10, v.getY() / 10, v.getZ() / 10, 1)); |
||||||
|
rootNode.getChild("Box").rotate(tpf, tpf, tpf); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateAttached(AppStateManager stateManager) { |
||||||
|
rootNode.attachChild(localRootNode); |
||||||
|
guiNode.attachChild(localGuiNode); |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateDetached(AppStateManager stateManager) { |
||||||
|
rootNode.detachChild(localRootNode); |
||||||
|
guiNode.detachChild(localGuiNode); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>SettingsScreenState.java</a></h2> |
||||||
|
<div> |
||||||
|
<pre>package chapter04.appstatedemo; |
||||||
|
|
||||||
|
import com.jme3.app.Application; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.app.state.AbstractAppState; |
||||||
|
import com.jme3.app.state.AppStateManager; |
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.font.BitmapFont; |
||||||
|
import com.jme3.font.BitmapText; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* A template how to create an Application State. This example state simply |
||||||
|
* changes the background color depending on the camera position. |
||||||
|
*/</span> |
||||||
|
public class SettingsScreenState extends AbstractAppState { |
||||||
|
|
||||||
|
private ViewPort viewPort; |
||||||
|
private Node rootNode; |
||||||
|
private Node guiNode; |
||||||
|
private AssetManager assetManager; |
||||||
|
private Node localRootNode = new Node("Settings Screen RootNode"); |
||||||
|
private Node localGuiNode = new Node("Settings Screen GuiNode"); |
||||||
|
private final ColorRGBA backgroundColor = ColorRGBA.DarkGray; |
||||||
|
|
||||||
|
public SettingsScreenState(SimpleApplication app) { |
||||||
|
this.rootNode = app.getRootNode(); |
||||||
|
this.viewPort = app.getViewPort(); |
||||||
|
this.guiNode = app.getGuiNode(); |
||||||
|
this.assetManager = app.getAssetManager(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
|
||||||
|
/** Load this scene */ |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
|
||||||
|
Box(new Vector3f(-1, -1, 0), .5f, .5f, .5f); |
||||||
|
Geometry geom = new Geometry("Box", mesh); |
||||||
|
Material mat = new Material(assetManager, |
||||||
|
"Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat.setColor("Color", ColorRGBA.Red); |
||||||
|
geom.setMaterial(mat); |
||||||
|
geom.setLocalTranslation(1, 0, 0); |
||||||
|
localRootNode.attachChild(geom); |
||||||
|
|
||||||
|
/** Load the HUD */ |
||||||
|
BitmapFont guiFont = assetManager.loadFont( |
||||||
|
"Interface/Fonts/Default.fnt"); |
||||||
|
BitmapText displaytext = new BitmapText(guiFont); |
||||||
|
displaytext.setSize(guiFont.getCharSet().getRenderedSize()); |
||||||
|
displaytext.move(10, displaytext.getLineHeight() + 20, 0); |
||||||
|
displaytext.setText("Settings screen. Press RETURN to save " |
||||||
|
+ "and return to start screen."); |
||||||
|
localGuiNode.attachChild(displaytext); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
/** the action happens here */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateAttached(AppStateManager stateManager) { |
||||||
|
rootNode.attachChild(localRootNode); |
||||||
|
guiNode.attachChild(localGuiNode); |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateDetached(AppStateManager stateManager) { |
||||||
|
rootNode.detachChild(localRootNode); |
||||||
|
guiNode.detachChild(localGuiNode); |
||||||
|
} |
||||||
|
|
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>StartScreenState.java</a></h2> |
||||||
|
<div> |
||||||
|
<pre>package chapter04.appstatedemo; |
||||||
|
|
||||||
|
import com.jme3.app.Application; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.app.state.AbstractAppState; |
||||||
|
import com.jme3.app.state.AppStateManager; |
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.font.BitmapFont; |
||||||
|
import com.jme3.font.BitmapText; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* A template how to create an Application State. This example state simply |
||||||
|
* changes the background color depending on the camera position. |
||||||
|
*/</span> |
||||||
|
public class StartScreenState extends AbstractAppState { |
||||||
|
|
||||||
|
private ViewPort viewPort; |
||||||
|
private Node rootNode; |
||||||
|
private Node guiNode; |
||||||
|
private AssetManager assetManager; |
||||||
|
private Node localRootNode = new Node("Start Screen RootNode"); |
||||||
|
private Node localGuiNode = new Node("Start Screen GuiNode"); |
||||||
|
private final ColorRGBA backgroundColor = ColorRGBA.Gray; |
||||||
|
|
||||||
|
public StartScreenState(SimpleApplication app){ |
||||||
|
this.rootNode = app.getRootNode(); |
||||||
|
this.viewPort = app.getViewPort(); |
||||||
|
this.guiNode = app.getGuiNode(); |
||||||
|
this.assetManager = app.getAssetManager(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
|
||||||
|
/** Init this scene */ |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
|
||||||
|
Box(new Vector3f(-1,1,0), .5f,.5f,.5f); |
||||||
|
Geometry geom = new Geometry("Box", mesh); |
||||||
|
Material mat = new Material(assetManager, |
||||||
|
"Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat.setColor("Color", ColorRGBA.Yellow); |
||||||
|
geom.setMaterial(mat); |
||||||
|
geom.setLocalTranslation(1, 0, 0); |
||||||
|
localRootNode.attachChild(geom); |
||||||
|
|
||||||
|
/** Load a HUD */ |
||||||
|
BitmapFont guiFont = assetManager.loadFont( |
||||||
|
"Interface/Fonts/Default.fnt"); |
||||||
|
BitmapText displaytext = new BitmapText(guiFont); |
||||||
|
displaytext.setSize(guiFont.getCharSet().getRenderedSize()); |
||||||
|
displaytext.move( 10, displaytext.getLineHeight() + 20, 0); |
||||||
|
displaytext.setText("Start screen. Press BACKSPACE to resume the game, " |
||||||
|
+ "press RETURN to edit Settings."); |
||||||
|
localGuiNode.attachChild(displaytext); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
/** the action happens here */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateAttached(AppStateManager stateManager) { |
||||||
|
rootNode.attachChild(localRootNode); |
||||||
|
guiNode.attachChild(localGuiNode); |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateDetached(AppStateManager stateManager) { |
||||||
|
rootNode.detachChild(localRootNode); |
||||||
|
guiNode.detachChild(localGuiNode); |
||||||
|
} |
||||||
|
|
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:appstatesdemo?do=export_xhtmlbody">view online version</a></em></p> |
@ -1,4 +1,47 @@ |
|||||||
<h1><a>Multithreading Bullet Physics in jme3</a></h1><div></div><h2><a>Introduction</a></h2><div><p>Since bullet is not (yet) multithreaded or GPU accelerated the jME3 implementation allows to run each physics space on a separate thread that is executed in parallel to rendering.</p></div><h2><a>How is it handled in jme3 and bullet?</a></h2><div><p>A SimpleApplication with a BulletAppState allows setting the threading type via</p><pre>setThreadingType(ThreadingType type);</pre><p>where ThreadingType can be either SEQUENTIAL or PARALLEL.</p><p>In the simpleInitApp() method:</p><pre>bulletAppState = new BulletAppState(); |
|
||||||
|
<h1><a>Multithreading Bullet Physics in jme3</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Introduction</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
Since bullet is not (yet) multithreaded or GPU accelerated the jME3 implementation allows to run each physics space on a separate thread that is executed in parallel to rendering. |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>How is it handled in jme3 and bullet?</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
A SimpleApplication with a BulletAppState allows setting the threading type via |
||||||
|
</p> |
||||||
|
<pre>setThreadingType(ThreadingType type);</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
where ThreadingType can be either SEQUENTIAL or PARALLEL. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
In the simpleInitApp() method: |
||||||
|
|
||||||
|
</p> |
||||||
|
<pre>bulletAppState = new BulletAppState(); |
||||||
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL); |
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL); |
||||||
stateManager.attach(bulletAppState);</pre><p>The physics update happens in parallel to rendering, after the users changes have been made in the update() call. This way the loop logic is still maintained: the user can set and change values in physics and scenegraph objects before render() and physicsUpdate() are called in parallel. More physics spaces can simply be added by using multiple bulletAppStates.</p><div><span><a href="/wiki/doku.php/tag:documentation?do=showtag&tag=tag%3Adocumentation">documentation</a>, <a href="/wiki/doku.php/tag:physics?do=showtag&tag=tag%3Aphysics">physics</a>, <a href="/wiki/doku.php/tag:threading?do=showtag&tag=tag%3Athreading">threading</a> </span></div></div> |
stateManager.attach(bulletAppState);</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
The physics update happens in parallel to rendering, after the users changes have been made in the update() call. This way the loop logic is still maintained: the user can set and change values in physics and scenegraph objects before render() and physicsUpdate() are called in parallel. More physics spaces can simply be added by using multiple bulletAppStates. |
||||||
|
</p> |
||||||
|
<div><span> |
||||||
|
<a href="/wiki/doku.php/tag:documentation?do=showtag&tag=tag%3Adocumentation">documentation</a>, |
||||||
|
<a href="/wiki/doku.php/tag:physics?do=showtag&tag=tag%3Aphysics">physics</a>, |
||||||
|
<a href="/wiki/doku.php/tag:threading?do=showtag&tag=tag%3Athreading">threading</a> |
||||||
|
</span></div> |
||||||
|
|
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:bullet_multithreading?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:bullet_multithreading?do=export_xhtmlbody">view online version</a></em></p> |
After Width: | Height: | Size: 51 KiB |
@ -0,0 +1,652 @@ |
|||||||
|
|
||||||
|
<h1><a>Capture Audio/Video to a File</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
<p><div>A/V recording is still in development. |
||||||
|
It works for all of jMonkeyEngine's test cases. |
||||||
|
If you experience any problems or |
||||||
|
if something isn't clear, please <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://jmonkeyengine.org/members/bortreb/"><param name="text" value="<html><u>let me know</u></html>"><param name="textColor" value="blue"></object>. – bortreb |
||||||
|
</div></p> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
So you've made your cool new JMonkeyEngine3 game and you want to |
||||||
|
create a demo video to show off your hard work. Or maybe you want to |
||||||
|
make a cutscene for your game using the physics and characters in the |
||||||
|
game itself. Screen capturing is the most straightforward way to do |
||||||
|
this, but it can slow down your game and produce low-quality video and |
||||||
|
audio as a result. A better way is to record video and audio directly |
||||||
|
from the game while it is running. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<p><div>Combine this method with jMonkeyEngine's |
||||||
|
<a href="/com/jme3/gde/core/docs/jme3/advanced/cinematics.html">Cinematics</a> |
||||||
|
feature to record high-quality game trailers! |
||||||
|
</div></p> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Simple Way</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
First off, if all you need is to record video at 30fps with no sound, then look |
||||||
|
no further then jMonkeyEngine3's built in <code>VideoRecorderAppState</code> |
||||||
|
class. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
Add the following code to your <code>simpleInitApp()</code> method. |
||||||
|
</p> |
||||||
|
<pre>stateManager.attach(new VideoRecorderAppState()); //start recording</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
The game will run slow, but the recording will be in high-quality and |
||||||
|
normal speed. The video files will be stored in your user home |
||||||
|
directory, if you want to save to another file, specify it in the |
||||||
|
VideoRecorderAppState constructor. Recording starts when the state is |
||||||
|
attached and ends when the application quits or the state is detached. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
That's all! |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Advanced Way</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
If you want to record audio as well, record at different framerates, |
||||||
|
or record from multiple viewpoints at once, then there's a full |
||||||
|
solution for doing this already made for you here: |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.aurellem.com/releases/jmeCapture-latest.zip"><param name="text" value="<html><u>http://www.aurellem.com/releases/jmeCapture-latest.zip</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.aurellem.com/releases/jmeCapture-latest.tar.bz2"><param name="text" value="<html><u>http://www.aurellem.com/releases/jmeCapture-latest.tar.bz2</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
Download the archive in your preferred format, extract, |
||||||
|
add the jars to your project, and you are ready to go. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
The javadoc is here: |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.aurellem.com/jmeCapture/docs/"><param name="text" value="<html><u>http://www.aurellem.com/jmeCapture/docs/</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
To capture video and audio you use the |
||||||
|
<code>com.aurellem.capture.Capture</code> class, which has two methods, |
||||||
|
<code>captureAudio()</code> and <code>captureVideo()</code>, and the |
||||||
|
<code>com.aurellem.capture.IsoTimer</code> class, which sets the audio and |
||||||
|
video framerate. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
The steps are: |
||||||
|
</p> |
||||||
|
<pre>yourApp.setTimer(new IsoTimer(desiredFramesPerSecond));</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
This causes jMonkeyEngine to take as much time as it needs to fully |
||||||
|
calculate every frame of the video and audio. You will see your game |
||||||
|
speed up and slow down depending on how computationally demanding your |
||||||
|
game is, but the final recorded audio and video will be perfectly |
||||||
|
sychronized and will run at exactly the fps which you specified. |
||||||
|
</p> |
||||||
|
<pre>captureVideo(yourApp, targetVideoFile); |
||||||
|
captureAudio(yourApp, targetAudioFile);</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
These will cause the app to record audio and video when it is run. |
||||||
|
Audio and video will stop being recorded when the app stops. Your |
||||||
|
audio will be recorded as a 44,100 Hz linear PCM wav file, while the |
||||||
|
video will be recorded according to the following rules: |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
1.) (Preferred) If you supply an empty directory as the file, then |
||||||
|
the video will be saved as a sequence of .png files, one file per |
||||||
|
frame. The files start at 0000000.png and increment from there. |
||||||
|
You can then combine the frames into your preferred |
||||||
|
container/codec. If the directory is not empty, then writing |
||||||
|
video frames to it will fail, and nothing will be written. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
2.) If the filename ends in ".avi" then the frames will be encoded as |
||||||
|
a RAW stream inside an AVI 1.0 container. The resulting file |
||||||
|
will be quite large and you will probably want to re-encode it to |
||||||
|
your preferred container/codec format. Be advised that some |
||||||
|
video payers cannot process AVI with a RAW stream, and that AVI |
||||||
|
1.0 files generated by this method that exceed 2.0GB are invalid |
||||||
|
according to the AVI 1.0 <acronym title="specification">spec</acronym> (but many programs can still deal |
||||||
|
with them.) Thanks to |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.randelshofer.ch/blog/2008/08/writing-avi-videos-in-pure-java/"><param name="text" value="<html><u>Werner Randelshofer</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
for his excellent work which made the AVI file writer option possible. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
3.) Any non-directory file ending in anything other than ".avi" will |
||||||
|
be processed through Xuggle. Xuggle provides the option to use |
||||||
|
many codecs/containers, but you will have to install it on your |
||||||
|
system yourself in order to use this option. Please visit |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.xuggle.com/"><param name="text" value="<html><u>http://www.xuggle.com/</u></html>"><param name="textColor" value="blue"></object> to learn how to do this. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
Note that you will not hear any sound if you choose to record sound to |
||||||
|
a file. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>Basic Example</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Here is a complete example showing how to capture both audio and video |
||||||
|
from one of jMonkeyEngine3's advanced demo applications. |
||||||
|
</p> |
||||||
|
<pre>import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import jme3test.water.TestPostWater; |
||||||
|
|
||||||
|
import com.aurellem.capture.Capture; |
||||||
|
import com.aurellem.capture.IsoTimer; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
|
||||||
|
|
||||||
|
<span>/** |
||||||
|
* Demonstrates how to use basic Audio/Video capture with a |
||||||
|
* jMonkeyEngine application. You can use these techniques to make |
||||||
|
* high quality cutscenes or demo videos, even on very slow laptops. |
||||||
|
* |
||||||
|
* @author Robert McIntyre |
||||||
|
*/</span> |
||||||
|
|
||||||
|
public class Basic { |
||||||
|
|
||||||
|
public static void main(IOException{ |
||||||
|
File.createTempFile("JME-water-video", ".avi"); |
||||||
|
File.createTempFile("JME-water-audio", ".wav"); |
||||||
|
|
||||||
|
SimpleApplication app = new TestPostWater(); |
||||||
|
app.setTimer(new IsoTimer(60)); |
||||||
|
app.setShowSettings(false); |
||||||
|
|
||||||
|
Capture.captureVideo(app, video); |
||||||
|
Capture.captureAudio(app, audio); |
||||||
|
|
||||||
|
app.start(); |
||||||
|
|
||||||
|
System.out.println(video.getCanonicalPath()); |
||||||
|
System.out.println(audio.getCanonicalPath()); |
||||||
|
} |
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>How it works</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
A standard JME3 application that extends <code>SimpleApplication</code> or |
||||||
|
<code>Application</code> tries as hard as it can to keep in sync with |
||||||
|
<em>user-time</em>. If a ball is rolling at 1 game-mile per game-hour in the |
||||||
|
game, and you wait for one user-hour as measured by the clock on your |
||||||
|
wall, then the ball should have traveled exactly one game-mile. In |
||||||
|
order to keep sync with the real world, the game throttles its physics |
||||||
|
engine and graphics display. If the computations involved in running |
||||||
|
the game are too intense, then the game will first skip frames, then |
||||||
|
sacrifice physics accuracy. If there are particuraly demanding |
||||||
|
computations, then you may only get 1 fps, and the ball may tunnel |
||||||
|
through the floor or obstacles due to inaccurate physics simulation, |
||||||
|
but after the end of one user-hour, that ball will have traveled one |
||||||
|
game-mile. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
When we're recording video, we don't care if the game-time syncs with |
||||||
|
user-time, but instead whether the time in the recorded video |
||||||
|
(video-time) syncs with user-time. To continue the analogy, if we |
||||||
|
recorded the ball rolling at 1 game-mile per game-hour and watched the |
||||||
|
video later, we would want to see 30 fps video of the ball rolling at |
||||||
|
1 video-mile per <em>user-hour</em>. It doesn't matter how much user-time it |
||||||
|
took to simulate that hour of game-time to make the high-quality |
||||||
|
recording. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
The IsoTimer ignores real-time and always reports that the same amount |
||||||
|
of time has passed every time it is called. That way, one can put code |
||||||
|
to write each video/audio frame to a file without worrying about that |
||||||
|
code itself slowing down the game to the point where the recording |
||||||
|
would be useless. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>Advanced Example</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
The package from aurellem.com was made for AI research and can do more |
||||||
|
than just record a single stream of audio and video. You can use it |
||||||
|
to: |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
1.) Create multiple independent listeners that each hear the world |
||||||
|
from their own perspective. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
2.) Process the sound data in any way you wish. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
3.) Do the same for visual data. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
Here is a more advanced example, which can also be found along with |
||||||
|
other examples in the jmeCapture.jar file included in the |
||||||
|
distribution. |
||||||
|
</p> |
||||||
|
<pre>package com.aurellem.capture.examples; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFormat; |
||||||
|
|
||||||
|
import org.tritonus.share.sampled.FloatSampleTools; |
||||||
|
|
||||||
|
import com.aurellem.capture.AurellemSystemDelegate; |
||||||
|
import com.aurellem.capture.Capture; |
||||||
|
import com.aurellem.capture.IsoTimer; |
||||||
|
import com.aurellem.capture.audio.CompositeSoundProcessor; |
||||||
|
import com.aurellem.capture.audio.MultiListener; |
||||||
|
import com.aurellem.capture.audio.SoundProcessor; |
||||||
|
import com.aurellem.capture.audio.WaveFileWriter; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.audio.AudioNode; |
||||||
|
import com.jme3.audio.Listener; |
||||||
|
import com.jme3.cinematic.MotionPath; |
||||||
|
import com.jme3.cinematic.events.AbstractCinematicEvent; |
||||||
|
import com.jme3.cinematic.events.MotionTrack; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.scene.shape.Sphere; |
||||||
|
import com.jme3.system.AppSettings; |
||||||
|
import com.jme3.system.JmeSystem; |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* |
||||||
|
* Demonstrates advanced use of the audio capture and recording |
||||||
|
* features. Multiple perspectives of the same scene are |
||||||
|
* simultaneously rendered to different sound files. |
||||||
|
* |
||||||
|
* A key limitation of the way multiple listeners are implemented is |
||||||
|
* that only 3D positioning effects are realized for listeners other |
||||||
|
* than the main LWJGL listener. This means that audio effects such |
||||||
|
* as environment settings will *not* be heard on any auxiliary |
||||||
|
* listeners, though sound attenuation will work correctly. |
||||||
|
* |
||||||
|
* Multiple listeners as realized here might be used to make AI |
||||||
|
* entities that can each hear the world from their own perspective. |
||||||
|
* |
||||||
|
* @author Robert McIntyre |
||||||
|
*/</span> |
||||||
|
|
||||||
|
public class Advanced extends SimpleApplication { |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* You will see three grey cubes, a blue sphere, and a path which |
||||||
|
* circles each cube. The blue sphere is generating a constant |
||||||
|
* monotone sound as it moves along the track. Each cube is |
||||||
|
* listening for sound; when a cube hears sound whose intensity is |
||||||
|
* greater than a certain threshold, it changes its color from |
||||||
|
* grey to green. |
||||||
|
* |
||||||
|
* Each cube is also saving whatever it hears to a file. The |
||||||
|
* scene from the perspective of the viewer is also saved to a |
||||||
|
* video file. When you listen to each of the sound files |
||||||
|
* alongside the video, the sound will get louder when the sphere |
||||||
|
* approaches the cube that generated that sound file. This |
||||||
|
* shows that each listener is hearing the world from its own |
||||||
|
* perspective. |
||||||
|
* |
||||||
|
*/</span> |
||||||
|
public static void main(String[] args) { |
||||||
|
Advanced app = new Advanced(); |
||||||
|
AppSettings settings = new AppSettings(true); |
||||||
|
settings.setAudioRenderer(AurellemSystemDelegate.SEND); |
||||||
|
JmeSystem.setSystemDelegate(new AurellemSystemDelegate()); |
||||||
|
app.setSettings(settings); |
||||||
|
app.setShowSettings(false); |
||||||
|
app.setPauseOnLostFocus(false); |
||||||
|
|
||||||
|
|
||||||
|
try { |
||||||
|
Capture.captureVideo(app, File.createTempFile("advanced",".avi")); |
||||||
|
Capture.captureAudio(app, File.createTempFile("advanced", ".wav")); |
||||||
|
} |
||||||
|
catch (IOException e) {e.printStackTrace();} |
||||||
|
|
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private Geometry bell; |
||||||
|
private Geometry ear1; |
||||||
|
private Geometry ear2; |
||||||
|
private Geometry ear3; |
||||||
|
private AudioNode music; |
||||||
|
private MotionTrack motionControl; |
||||||
|
private IsoTimer motionTimer = new IsoTimer(60); |
||||||
|
|
||||||
|
private Geometry makeEar(Node root, Vector3f position){ |
||||||
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
Geometry ear = new Geometry("ear", new Box(1.0f, 1.0f, 1.0f)); |
||||||
|
ear.setLocalTranslation(position); |
||||||
|
mat.setColor("Color", ColorRGBA.Green); |
||||||
|
ear.setMaterial(mat); |
||||||
|
root.attachChild(ear); |
||||||
|
return ear; |
||||||
|
} |
||||||
|
|
||||||
|
private Vector3f[] path = new Vector3f[]{ |
||||||
|
// loop 1 |
||||||
|
new Vector3f(0, 0, 0), |
||||||
|
new Vector3f(0, 0, -10), |
||||||
|
new Vector3f(-2, 0, -14), |
||||||
|
new Vector3f(-6, 0, -20), |
||||||
|
new Vector3f(0, 0, -26), |
||||||
|
new Vector3f(6, 0, -20), |
||||||
|
new Vector3f(0, 0, -14), |
||||||
|
new Vector3f(-6, 0, -20), |
||||||
|
new Vector3f(0, 0, -26), |
||||||
|
new Vector3f(6, 0, -20), |
||||||
|
// loop 2 |
||||||
|
new Vector3f(5, 0, -5), |
||||||
|
new Vector3f(7, 0, 1.5f), |
||||||
|
new Vector3f(14, 0, 2), |
||||||
|
new Vector3f(20, 0, 6), |
||||||
|
new Vector3f(26, 0, 0), |
||||||
|
new Vector3f(20, 0, -6), |
||||||
|
new Vector3f(14, 0, 0), |
||||||
|
new Vector3f(20, 0, 6), |
||||||
|
new Vector3f(26, 0, 0), |
||||||
|
new Vector3f(20, 0, -6), |
||||||
|
new Vector3f(14, 0, 0), |
||||||
|
// loop 3 |
||||||
|
new Vector3f(8, 0, 7.5f), |
||||||
|
new Vector3f(7, 0, 10.5f), |
||||||
|
new Vector3f(6, 0, 20), |
||||||
|
new Vector3f(0, 0, 26), |
||||||
|
new Vector3f(-6, 0, 20), |
||||||
|
new Vector3f(0, 0, 14), |
||||||
|
new Vector3f(6, 0, 20), |
||||||
|
new Vector3f(0, 0, 26), |
||||||
|
new Vector3f(-6, 0, 20), |
||||||
|
new Vector3f(0, 0, 14), |
||||||
|
// begin ellipse |
||||||
|
new Vector3f(16, 5, 20), |
||||||
|
new Vector3f(0, 0, 26), |
||||||
|
new Vector3f(-16, -10, 20), |
||||||
|
new Vector3f(0, 0, 14), |
||||||
|
new Vector3f(16, 20, 20), |
||||||
|
new Vector3f(0, 0, 26), |
||||||
|
new Vector3f(-10, -25, 10), |
||||||
|
new Vector3f(-10, 0, 0), |
||||||
|
// come at me! |
||||||
|
new Vector3f(-28.00242f, 48.005623f, -34.648228f), |
||||||
|
new Vector3f(0, 0 , -20), |
||||||
|
}; |
||||||
|
|
||||||
|
private void createScene() { |
||||||
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
bell = new Geometry( "sound-emitter" , new Sphere(15,15,1)); |
||||||
|
mat.setColor("Color", ColorRGBA.Blue); |
||||||
|
bell.setMaterial(mat); |
||||||
|
rootNode.attachChild(bell); |
||||||
|
|
||||||
|
ear1 = makeEar(rootNode, new Vector3f(0, 0 ,-20)); |
||||||
|
ear2 = makeEar(rootNode, new Vector3f(0, 0 ,20)); |
||||||
|
ear3 = makeEar(rootNode, new Vector3f(20, 0 ,0)); |
||||||
|
|
||||||
|
MotionPath track = new MotionPath(); |
||||||
|
|
||||||
|
for (Vector3f v : path){ |
||||||
|
track.addWayPoint(v); |
||||||
|
} |
||||||
|
track.setCurveTension(0.80f); |
||||||
|
|
||||||
|
motionControl = new MotionTrack(bell,track); |
||||||
|
// for now, use reflection to change the timer... |
||||||
|
// motionControl.setTimer(new IsoTimer(60)); |
||||||
|
|
||||||
|
try { |
||||||
|
Field timerField; |
||||||
|
timerField = AbstractCinematicEvent.class.getDeclaredField("timer"); |
||||||
|
timerField.setAccessible(true); |
||||||
|
try {timerField.set(motionControl, motionTimer);} |
||||||
|
catch (IllegalArgumentException e) {e.printStackTrace();} |
||||||
|
catch (IllegalAccessException e) {e.printStackTrace();} |
||||||
|
} |
||||||
|
catch (SecurityException e) {e.printStackTrace();} |
||||||
|
catch (NoSuchFieldException e) {e.printStackTrace();} |
||||||
|
|
||||||
|
|
||||||
|
motionControl.setDirectionType(MotionTrack.Direction.PathAndRotation); |
||||||
|
motionControl.setRotation(new Quaternion().fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y)); |
||||||
|
motionControl.setInitialDuration(20f); |
||||||
|
motionControl.setSpeed(1f); |
||||||
|
|
||||||
|
track.enableDebugShape(assetManager, rootNode); |
||||||
|
positionCamera(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void positionCamera(){ |
||||||
|
this.cam.setLocation(new Vector3f(-28.00242f, 48.005623f, -34.648228f)); |
||||||
|
this.cam.setRotation(new Quaternion(0.3359635f, 0.34280345f, -0.13281013f, 0.8671653f)); |
||||||
|
} |
||||||
|
|
||||||
|
private void initAudio() { |
||||||
|
org.lwjgl.input.Mouse.setGrabbed(false); |
||||||
|
music = new AudioNode(assetManager, "Sound/Effects/Beep.ogg", false); |
||||||
|
|
||||||
|
rootNode.attachChild(music); |
||||||
|
audioRenderer.playSource(music); |
||||||
|
music.setPositional(true); |
||||||
|
music.setVolume(1f); |
||||||
|
music.setReverbEnabled(false); |
||||||
|
music.setDirectional(false); |
||||||
|
music.setMaxDistance(200.0f); |
||||||
|
music.setRefDistance(1f); |
||||||
|
//music.setRolloffFactor(1f); |
||||||
|
music.setLooping(false); |
||||||
|
audioRenderer.pauseSource(music); |
||||||
|
} |
||||||
|
|
||||||
|
public class Dancer implements SoundProcessor { |
||||||
|
Geometry entity; |
||||||
|
float scale = 2; |
||||||
|
public Dancer(Geometry entity){ |
||||||
|
this.entity = entity; |
||||||
|
} |
||||||
|
|
||||||
|
<span>/** |
||||||
|
* this method is irrelevant since there is no state to cleanup. |
||||||
|
*/</span> |
||||||
|
public void cleanup() {} |
||||||
|
|
||||||
|
|
||||||
|
<span>/** |
||||||
|
* Respond to sound! This is the brain of an AI entity that |
||||||
|
* hears its surroundings and reacts to them. |
||||||
|
*/</span> |
||||||
|
public void process(ByteBuffer audioSamples, int numSamples, AudioFormat format) { |
||||||
|
audioSamples.clear(); |
||||||
|
byte[] data = new byte[numSamples]; |
||||||
|
float[] out = new float[numSamples]; |
||||||
|
audioSamples.get(data); |
||||||
|
FloatSampleTools.byte2floatInterleaved(data, 0, out, 0, |
||||||
|
numSamples/format.getFrameSize(), format); |
||||||
|
|
||||||
|
float max = Float.NEGATIVE_INFINITY; |
||||||
|
for (float f : out){if (f > max) max = f;} |
||||||
|
audioSamples.clear(); |
||||||
|
|
||||||
|
if (max > 0.1){entity.getMaterial().setColor("Color", ColorRGBA.Green);} |
||||||
|
else {entity.getMaterial().setColor("Color", ColorRGBA.Gray);} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void prepareEar(Geometry ear, int n){ |
||||||
|
if (this.audioRenderer instanceof MultiListener){ |
||||||
|
MultiListener rf = (MultiListener)this.audioRenderer; |
||||||
|
|
||||||
|
Listener auxListener = new Listener(); |
||||||
|
auxListener.setLocation(ear.getLocalTranslation()); |
||||||
|
|
||||||
|
rf.addListener(auxListener); |
||||||
|
WaveFileWriter aux = null; |
||||||
|
|
||||||
|
try {aux = new WaveFileWriter(File.createTempFile("advanced-audio-" + n, ".wav"));} |
||||||
|
catch (IOException e) {e.printStackTrace();} |
||||||
|
|
||||||
|
rf.registerSoundProcessor(auxListener, |
||||||
|
new CompositeSoundProcessor(new Dancer(ear), aux)); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void simpleInitApp() { |
||||||
|
this.setTimer(new IsoTimer(60)); |
||||||
|
initAudio(); |
||||||
|
|
||||||
|
createScene(); |
||||||
|
|
||||||
|
prepareEar(ear1, 1); |
||||||
|
prepareEar(ear2, 1); |
||||||
|
prepareEar(ear3, 1); |
||||||
|
|
||||||
|
motionControl.play(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
motionTimer.update(); |
||||||
|
if (music.getStatus() != AudioNode.Status.Playing){ |
||||||
|
music.play(); |
||||||
|
} |
||||||
|
Vector3f loc = cam.getLocation(); |
||||||
|
Quaternion rot = cam.getRotation(); |
||||||
|
listener.setLocation(loc); |
||||||
|
listener.setRotation(rot); |
||||||
|
music.setLocalTranslation(bell.getLocalTranslation()); |
||||||
|
} |
||||||
|
|
||||||
|
}</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
<!--[if !IE]> --> |
||||||
|
<object class="media" width="400" height="350" type="application/x-shockwave-flash" data="/wiki/lib/exe/fetch.php?hash=568504&media=http%3A%2F%2Fwww.youtube.com%2Fv%2FoCEfK0yhDrY%3F.swf" > |
||||||
|
<!-- <![endif]--> |
||||||
|
<!--[if IE]> |
||||||
|
<object class="media" width="400" height="350" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" > |
||||||
|
<param name="movie" value="/wiki/lib/exe/fetch.php?hash=568504&media=http%3A%2F%2Fwww.youtube.com%2Fv%2FoCEfK0yhDrY%3F.swf" /> |
||||||
|
<!--><!-- --> |
||||||
|
<param name="quality" value="high" /> |
||||||
|
The <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.adobe.com/products/flashplayer/"><param name="text" value="<html><u>Adobe Flash Plugin</u></html>"><param name="textColor" value="blue"></object> is needed to display this content. |
||||||
|
</object> |
||||||
|
<!-- <![endif]--> |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>Using Advanced features to Record from more than one perspective at once</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
<!--[if !IE]> --> |
||||||
|
<object class="media" width="400" height="350" type="application/x-shockwave-flash" data="/wiki/lib/exe/fetch.php?hash=6921c2&media=http%3A%2F%2Fwww.youtube.com%2Fv%2FWIJt9aRGusc%3F.swf" > |
||||||
|
<!-- <![endif]--> |
||||||
|
<!--[if IE]> |
||||||
|
<object class="media" width="400" height="350" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" > |
||||||
|
<param name="movie" value="/wiki/lib/exe/fetch.php?hash=6921c2&media=http%3A%2F%2Fwww.youtube.com%2Fv%2FWIJt9aRGusc%3F.swf" /> |
||||||
|
<!--><!-- --> |
||||||
|
<param name="quality" value="high" /> |
||||||
|
The <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://www.adobe.com/products/flashplayer/"><param name="text" value="<html><u>Adobe Flash Plugin</u></html>"><param name="textColor" value="blue"></object> is needed to display this content. |
||||||
|
</object> |
||||||
|
<!-- <![endif]--> |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>More Information</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
This is the old page showing the first version of this idea |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://aurellem.org/cortex/html/capture-video.html"><param name="text" value="<html><u>http://aurellem.org/cortex/html/capture-video.html</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
All source code can be found here: |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://hg.bortreb.com/audio-send"><param name="text" value="<html><u>http://hg.bortreb.com/audio-send</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://hg.bortreb.com/jmeCapture"><param name="text" value="<html><u>http://hg.bortreb.com/jmeCapture</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
More information on the modifications to OpenAL to support multiple |
||||||
|
listeners can be found here. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://aurellem.org/audio-send/html/ear.html"><param name="text" value="<html><u>http://aurellem.org/audio-send/html/ear.html</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:capture_audio_video_to_a_file?do=export_xhtmlbody">view online version</a></em></p> |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 53 KiB |
@ -0,0 +1,49 @@ |
|||||||
|
|
||||||
|
<h1><a>Fade-in / Fade-out Effect</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
You can use a fade in/fade out effect to make smooth transitions, for example between game levels. The effect fades in from black to the initialized scene, or fades out from the scene to black. |
||||||
|
The effect uses com.jme3.post.FilterPostProcessor and com.jme3.post.filters.FadeFilter. |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Setting up</a></h2> |
||||||
|
<div> |
||||||
|
<ol> |
||||||
|
<li><div> Create one FilterPostProcessor object per application.</div> |
||||||
|
</li> |
||||||
|
<li><div> Create a FadeFilter object.</div> |
||||||
|
</li> |
||||||
|
<li><div> Give the FadeFilter constructor the fade duration in seconds as parameter. If you use the parameter-less constructor, the duration is 1 sec by default.</div> |
||||||
|
</li> |
||||||
|
<li><div> Add the FadeFilter to the FilterPostProcessor.</div> |
||||||
|
</li> |
||||||
|
<li><div> Add the FilterPostProcessor to the default viewPort.</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
<pre>private FilterPostProcessor fpp; |
||||||
|
private FadeFilter fade; |
||||||
|
public void simpleInitApp() { |
||||||
|
... |
||||||
|
fpp = new FilterPostProcessor(assetManager); |
||||||
|
fade = new FadeFilter(2); // e.g. 2 seconds |
||||||
|
fpp.addFilter(fade); |
||||||
|
viewPort.addProcessor(fpp); |
||||||
|
... |
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Fading in and out</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
Now call the <code>fade.fadeIn()</code> and <code>fade.fadeOut()</code> methods to trigger the effect. |
||||||
|
You can also change the fade duration using <code>fade.setDuration()</code>. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:fade?do=export_xhtmlbody">view online version</a></em></p> |
After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,92 @@ |
|||||||
|
|
||||||
|
<h1><a>Nifty GUI: Create a PopUp Menu</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Even though you create and populate the popup menu in Java, you still need a "placeholder" in your <acronym title="Extensible Markup Language">XML</acronym> file. |
||||||
|
The popup menu <code>niftyPopupMenu</code> is a default Control from <code>nifty-default-controls.xml</code>. |
||||||
|
</p> |
||||||
|
<pre><span><useControls filename="nifty-default-controls.xml"/></span> |
||||||
|
... |
||||||
|
<span><popup id="niftyPopupMenu" childLayout="absolute-inside"</span> |
||||||
|
<span> controller="ControllerOfYourChoice" width="10%"></span> |
||||||
|
<span><interact onClick="closePopup()" onSecondaryClick="closePopup()" onTertiaryClick="closePopup()" /></span> |
||||||
|
<span><control id="#menu" name="niftyMenu" /></span> |
||||||
|
<span><span></popup></span></span> |
||||||
|
...</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
A brief explanation of some the attributes above: |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> The popup id is used within your Java code so that nifty knows which popup placeholder to create.</div> |
||||||
|
</li> |
||||||
|
<li><div> The Controller tells Nifty which Java class handles MenuItemActivatedEvent.</div> |
||||||
|
</li> |
||||||
|
<li><div> The on(Secondary/Tertiary)Click tells Nifty to close the popup if the user clicks anywhere except on the menu items (in this example)</div> |
||||||
|
</li> |
||||||
|
<li><div> The control id is used by the Java class to define a control type (i.e. Menu)</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
The Java code within your defined ScreenController implementation: |
||||||
|
</p> |
||||||
|
<pre>private Element popup; |
||||||
|
... |
||||||
|
public void createMyPopupMenu(){ |
||||||
|
popup = nifty.createPopup("niftyPopupMenu"); |
||||||
|
Menu.class); |
||||||
|
myMenu.setWidth(new SizeValue("100px")); // must be set |
||||||
|
myMenu.addMenuItem("Click me!", "menuItemIcon.png", |
||||||
|
new menuItem("menuItemid", "blah blah")); // menuItem is a custom class |
||||||
|
nifty.subscribe( |
||||||
|
nifty.getCurrentScreen(), |
||||||
|
myMenu.getId(), |
||||||
|
MenuItemActivatedEvent.class, |
||||||
|
new MenuItemActivatedEventSubscriber()); |
||||||
|
} |
||||||
|
|
||||||
|
public void showMenu() { // the method to trigger the menu |
||||||
|
// If this is a menu that is going to be used many times, then |
||||||
|
// call this in your constructor rather than here |
||||||
|
createMyPopupMenu() |
||||||
|
// call the popup to screen of your choice: |
||||||
|
nifty.showPopup(nifty.getCurrentScreen(), popup.getId(), null); |
||||||
|
} |
||||||
|
|
||||||
|
private class menuItem { |
||||||
|
public String id; |
||||||
|
public String name; |
||||||
|
public menuItem(String name){ |
||||||
|
this.id= id; |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
}</pre> |
||||||
|
<ul> |
||||||
|
<li><div> The createMyPopupMenu() method creates the menu with set width so that you can populate it.</div> |
||||||
|
</li> |
||||||
|
<li><div> The showMenu() method is called by something to trigger the menu (i.e. could be a Key or some other method).</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
To handle menu item events (i.e. calling a method when you click on a menu item), you register (subscribe) a EventTopicSubscriber<MenuItemActivatedEvent> class implementation to a nifty screen and element. |
||||||
|
</p> |
||||||
|
<pre> private class MenuItemActivatedEventSubscriber |
||||||
|
implements EventTopicSubscriber<MenuItemActivatedEvent> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onEvent(final String id, final MenuItemActivatedEvent event) { |
||||||
|
menuItem item = (menuItem) event.getItem(); |
||||||
|
if ("menuItemid".equals(item.id)) { |
||||||
|
//do something !!! |
||||||
|
} |
||||||
|
} |
||||||
|
};</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_popup_menu?do=export_xhtmlbody">view online version</a></em></p> |
@ -0,0 +1,345 @@ |
|||||||
|
|
||||||
|
<h1><a>Nifty GUI 1.3 Scenarios</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
This document contains best practices for typical NiftyGUI usercase scenarios. These tips assume that you have read the <a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui.html">Introduction to jME3's Nifty GUI integration</a> first, and have laid out a basic <acronym title="Graphical User Interface">GUI</acronym> that interacts with your Java application. Here you learn how you integrate the <acronym title="Graphical User Interface">GUI</acronym> better, and add effects and advanced controls. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Java or XML?</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
You can build Nifty GUIs using <acronym title="Extensible Markup Language">XML</acronym> or Java syntax. Which one should you choose? |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> Build your basic static UI layout using <acronym title="Extensible Markup Language">XML</acronym> - it's cleaner to write and read. </div> |
||||||
|
</li> |
||||||
|
<li><div> While the game runs, you dynamically change the UI content using Java code. </div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
This approach has the advantage that you can, for example, switch between a phone and a desktop UI by simply swapping one base <acronym title="Extensible Markup Language">XML</acronym> file. You design the swappable UI with different layouts, but use the same element IDs, so your dynamic Java code works the same no matetr which base <acronym title="Extensible Markup Language">XML</acronym> layout you use it on. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Switch Game States</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
In a JME game, you typically have three game states: |
||||||
|
</p> |
||||||
|
<ol> |
||||||
|
<li><div> Stopped: The game is stopped, a StartScreen is displayed. </div> |
||||||
|
</li> |
||||||
|
<li><div> Running: The game is running, the in-game HudScreen is displayed. </div> |
||||||
|
</li> |
||||||
|
<li><div> Paused: The game is paused, a PausedScreen is displayed.</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
(Aside: Additionally, the Stopped state often contains a LoadScreen, LogonScreen, OptionsScreen, CharacterCreationScreen, HighScoreScreen, CreditsScreen, etc. Some games let you access the OptionsScreen in the Paused state as well. The Running state can also contain an InventoryScreen, ItemShopScreen, StatsScreen, SkillScreen, etc.) |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
In JME, game states are implemented as custom <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">AppState</a> objects. Write each AppState so it brings its own input mappings, rootNode content, update loop behaviour, etc with it. |
||||||
|
</p> |
||||||
|
<ol> |
||||||
|
<li><div> Stopped: StartScreen AppState + GuiInputs AppState</div> |
||||||
|
</li> |
||||||
|
<li><div> Paused: PausedScreen AppState + GuiInputs AppState</div> |
||||||
|
</li> |
||||||
|
<li><div> Running: HudScreen AppState + InGameInputs AppState + BulletAppState (jme physics), …</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
When the player switches between game states, you detach one set of AppStates, and attach another. For example, when the player pauses the running game, you use a boolean switch to pause the game loop and deactivate the game inputs (shooting, navigation). The screen is overlayed with a PausedScreen, which contains a visible mouse pointer and a Continue button. When the player clicks Continue, the mouse pointer is deactivated, the in-game input and navigational mappings are activated, and the game loop continues. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Get Access to Application and Update Loop</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Since you are writing a jME3 application, you can additionally make any ScreenController class extend the <a href="/com/jme3/gde/core/docs/jme3/advanced/application_states.html">AbstractAppState</a> class. |
||||||
|
This gives the ScreenController access to the application object and to the update loop! |
||||||
|
</p> |
||||||
|
<pre>public class StartScreenState extends AbstractAppState { |
||||||
|
|
||||||
|
private ViewPort viewPort; |
||||||
|
private Node rootNode; |
||||||
|
private Node guiNode; |
||||||
|
private AssetManager assetManager; |
||||||
|
private Node localRootNode = new Node("Start Screen RootNode"); |
||||||
|
private Node localGuiNode = new Node("Start Screen GuiNode"); |
||||||
|
private final ColorRGBA backgroundColor = ColorRGBA.Gray; |
||||||
|
|
||||||
|
public StartScreenState(SimpleApplication app){ |
||||||
|
this.rootNode = app.getRootNode(); |
||||||
|
this.viewPort = app.getViewPort(); |
||||||
|
this.guiNode = app.getGuiNode(); |
||||||
|
this.assetManager = app.getAssetManager(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
/** init the screen */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
/** any main loop action happens here */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateAttached(AppStateManager stateManager) { |
||||||
|
rootNode.attachChild(localRootNode); |
||||||
|
guiNode.attachChild(localGuiNode); |
||||||
|
viewPort.setBackgroundColor(backgroundColor); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stateDetached(AppStateManager stateManager) { |
||||||
|
rootNode.detachChild(localRootNode); |
||||||
|
guiNode.detachChild(localGuiNode); |
||||||
|
} |
||||||
|
|
||||||
|
}</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Know Your Variables</a></h2> |
||||||
|
<div> |
||||||
|
<div><table> |
||||||
|
<tr> |
||||||
|
<th>Variable</th><th>Description</th> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>${CALL.myMethod()} </td><td> Calls a method in the current ScreenController and gets the method's return String. The method can also be void and have a side effect, e.g. play a sound etc.</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>${ENV.HOME}</td><td> Returns the path to user's home directory.</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>${ENV.key} </td><td> Looks up <code>key</code> in the environment variables. Use it like Java's System.getEnv("key").</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>${PROP.key}</td><td> looks up <code>key</code> in the Nifty properties. Use Nifty.setGlobalproperties(properties) and Nifty.getGlobalproperties("key"). Or SystemGetProperties(key);</td> |
||||||
|
</tr> |
||||||
|
</table></div> |
||||||
|
<!-- EDIT1 TABLE [4107-4638] --> |
||||||
|
<p> |
||||||
|
|
||||||
|
See also: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=MarkUp</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Use ScreenControllers for Mutally Exclusive Functionality</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Technically you are free to create one ScreenController class for each screen, or reuse the same ScreenController for all or some of them. In the end it may be best to create individual ScreenControllers for functionality that is mutually exclusive. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
For example, create a <code>MyHudScreen.java</code> for the <code>hud</code> screen, and a <code>MyStartScreen.java</code> for the <code>start</code> screen. |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> Include all user interface methods that are needed during the game (while the HUD is up) in <code>MyHudScreen.java</code>. Then make this class control all screens that can be up during the game (the HUD screen, a MiniMap screen, an Inventory screen, an Abilities or Skills screen, etc). All these screens possibly share data (game data, player data), so it makes sense to control them all with methods of the same <code>MyHudScreen.java</code> class.</div> |
||||||
|
</li> |
||||||
|
<li><div> The start screen, however, is mostly independent of the running game. Include all user interface methods that are needed outside the game (while you are on the start screen) in <code>MyStartScreen.java</code>. Then make this class control all screens that can be up outside the game (the Start screen, a Settings/Options screen, a HighScore screen, etc). All these classes need to read and write saved game data, so it makes sense to control them all with methods of the same <code>MyStartScreen.java</code> class.</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Create a Load Screen</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
<a href="/com/jme3/gde/core/docs/jme3/advanced/loading_screen.html">loading_screen</a> |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Create a Popup Menu</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
<a href="/com/jme3/gde/core/docs/jme3/advanced/nifty_gui_popup_menu.html">nifty GUI PopUp Menu</a> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Add Visual Effects</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
You can register effects to screen elements. |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> Respond to element events such as onStartScreen, onEndScreen, onHover, onFocus, onActive,</div> |
||||||
|
</li> |
||||||
|
<li><div> Trigger effects that change movement, blending, size, color, fading, and much more.</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Here is an example that moves a panel when the startScreen opens. You place an < effect > tag inside the element that you want to be affected. |
||||||
|
</p> |
||||||
|
<pre><span><panel height="25%" width="35%" ...></span> |
||||||
|
<span><span><effect></span></span> |
||||||
|
<span><onStartScreen name="move" mode="in" direction="top" length="300" startDelay="0" inherit="true"/></span> |
||||||
|
<span><span></effect></span></span> |
||||||
|
<span><span></panel></span></span></pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
Learn more from the NiftyGUI page: |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects</u></html>"><param name="textColor" value="blue"></object></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Add Sound Effects</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Playing sounds using Nifty is also possible with a <code>playSound</code> effect as trigger. Remember to first register the sound that you want to play: |
||||||
|
</p> |
||||||
|
<pre><span><registerSound id="myclick" filename="Interface/sounds/ButtonClick.ogg" /></span> |
||||||
|
... |
||||||
|
<span><span><label></span></span> |
||||||
|
<span><span><effect></span></span> |
||||||
|
<span><onClick name="playSound" sound="myclick"/></span> |
||||||
|
<span><span></effect></span></span> |
||||||
|
<span><span></label></span></span></pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Pass ClickLoc From Nifty to Java</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
After a mouse click, you may want to record the 2D clickLoc and send this info to your Java application. Typical ScreenController methods however only have a String argument. You'd have to convert the String to ints. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
To pass the clickLoc as two ints, you can use the special <code>(int x, int y)</code> syntax in the ScreenController: |
||||||
|
|
||||||
|
</p> |
||||||
|
<pre> public void clicked(int x, int y) { |
||||||
|
// here you can use the x and y of the clickLoc |
||||||
|
}</pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
In the Nifty <acronym title="Graphical User Interface">GUI</acronym> screen code (e.g. <acronym title="Extensible Markup Language">XML</acronym> file) you must call the <code>(int x, int y)</code> method <em>without</em> any parameters! |
||||||
|
|
||||||
|
</p> |
||||||
|
<pre><span><interact onClick="clicked()"/></span> </pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
You can name the method (here <code>clicked</code>) what ever you like, as long as you keep the argument syntax. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Loading Several XML Files</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
The basic Nifty <acronym title="Graphical User Interface">GUI</acronym> example showed how to use the <code>nifty.fromXML()</code> method to load one <acronym title="Extensible Markup Language">XML</acronym> file containing all Nifty <acronym title="Graphical User Interface">GUI</acronym> screens. |
||||||
|
The following code sample shows how you can load several <acronym title="Extensible Markup Language">XML</acronym> files into one nifty object. Loading several files with <code>nifty.addXml()</code> allows you to use one <acronym title="Extensible Markup Language">XML</acronym> file per one screen layout. |
||||||
|
</p> |
||||||
|
<pre>NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, viewPort); |
||||||
|
Nifty nifty = niftyDisplay.getNifty(); |
||||||
|
nifty.addXml("Interface/Screens/OptionsScreen.xml"); |
||||||
|
nifty.addXml("Interface/Screens/StartScreen.xml"); |
||||||
|
nifty.gotoScreen("startScreen"); |
||||||
|
StartScreenControl screenControl = (StartScreenControl) nifty.getScreen("startScreen").getScreenController(); |
||||||
|
OptionsScreenControl optionsControl = (OptionsScreenControl) nifty.getScreen("optionsScreen").getScreenController(); |
||||||
|
stateManager.attach(screenControl); |
||||||
|
stateManager.attach(optionsControl); |
||||||
|
guiViewPort.addProcessor(niftyDisplay);</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Design Your Own Styles</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
By default, your Nifty <acronym title="Extensible Markup Language">XML</acronym> screens use the built.in styles: |
||||||
|
</p> |
||||||
|
<pre> <span><useStyles filename="nifty-default-styles.xml" /></span> </pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
But you can switch to a set of custom styles in your game project's asset directory like this: |
||||||
|
</p> |
||||||
|
<pre> <span><useStyles filename="Interface/Styles/myCustomStyles.xml" /></span> </pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
Inside myCustomStyles.xml you define styles like this: |
||||||
|
</p> |
||||||
|
<pre><span><?xml version="1.0" encoding="UTF-8"?></span> |
||||||
|
<span><span><nifty-styles></span></span> |
||||||
|
<span><useStyles filename="Interface/Styles/Font/myCustomFontStyle.xml" /></span> |
||||||
|
<span><useStyles filename="Interface/Styles/Button/myCustomButtonStyle.xml" /></span> |
||||||
|
<span><useStyles filename="Interface/Styles/Label/myCustomLabelStyle.xml" /></span> |
||||||
|
... |
||||||
|
<span><span></nifty-styles></span></span></pre> |
||||||
|
|
||||||
|
<p> |
||||||
|
Learn more about how to create styles by looking at the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Build_from_Source"><param name="text" value="<html><u>Nifty GUI source code</u></html>"><param name="textColor" value="blue"></object> for “nifty-style-black”. Copy it as a template and change it to create your own style. |
||||||
|
|
||||||
|
</p> |
||||||
|
<hr /> |
||||||
|
|
||||||
|
<p> |
||||||
|
Learn more from the NiftyGUI page: |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects"><param name="text" value="<html><u>http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Effects</u></html>"><param name="textColor" value="blue"></object></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div><span> |
||||||
|
<a href="/wiki/doku.php/tag:gui?do=showtag&tag=tag%3Agui">gui</a>, |
||||||
|
<a href="/wiki/doku.php/tag:documentation?do=showtag&tag=tag%3Adocumentation">documentation</a>, |
||||||
|
<a href="/wiki/doku.php/tag:nifty?do=showtag&tag=tag%3Anifty">nifty</a>, |
||||||
|
<a href="/wiki/doku.php/tag:hud?do=showtag&tag=tag%3Ahud">hud</a>, |
||||||
|
<a href="/wiki/doku.php/tag:click?do=showtag&tag=tag%3Aclick">click</a>, |
||||||
|
<a href="/wiki/doku.php/tag:state?do=showtag&tag=tag%3Astate">state</a>, |
||||||
|
<a href="/wiki/doku.php/tag:states?do=showtag&tag=tag%3Astates">states</a>, |
||||||
|
<a href="/wiki/doku.php/tag:sound?do=showtag&tag=tag%3Asound">sound</a>, |
||||||
|
<a href="/wiki/doku.php/tag:effect?do=showtag&tag=tag%3Aeffect">effect</a> |
||||||
|
</span></div> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_scenarios?do=export_xhtmlbody">view online version</a></em></p> |
After Width: | Height: | Size: 360 KiB |
After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 97 KiB |
@ -1,2 +1,56 @@ |
|||||||
<h1><a>Building jMonkeyEngine 3 from the Sources</a></h1><div><p>We recommend downloading the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/downloads/list"><param name="text" value="<html><u>jMonkeyEngine SDK</u></html>"><param name="textColor" value="blue"></object> - but of course you can also build the jMonkeyEngine yourself from the sources. In this case, you need the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://subversion.tigris.org"><param name="text" value="<html><u>Subversion</u></html>"><param name="textColor" value="blue"></object> file version system installed (svn).</p><ol><li><div><strong>Checkout:</strong> Checkout the Subversion repository.<pre>svn checkout http://jmonkeyengine.googlecode.com/svn/trunk/engine jme3</pre></div><ul><li><div>You can leave login and password empty</div></li></ul></li><li><div><strong>Build:</strong> Execute <code>ant jar</code></div><ul><li><div>This compiles the JAR files in <code>dist/libs/*</code></div></li></ul></li><li><div><strong>Javadoc:</strong> Execute <code>ant javadoc</code></div><ul><li><div>This generates javadocs in the <code>dist/javadoc</code> directory.</div></li></ul></li><li><div><strong>Run:</strong> Execute <code>ant run</code></div><ul><li><div>This runs the TestChooser where you can browse examples.</div></li></ul></li><li><div><strong>Use:</strong> Create a Java SE project and place all JARs from the <code>dist/lib</code> directory on the classpath.</div><ul><li><div>You can now extend your first game from <code>com.jme3.app.SimpleApplication</code>.</div></li></ul></li></ol><hr /><p>Learn more about:</p><ul><li><div><a href="/com/jme3/gde/core/docs/jme3/simpleapplication_from_the_commandline.html">Setting up JME3 on the commandline (generic)</a>.</div></li><li><div><a href="/com/jme3/gde/core/docs/jme3/build_jme3_sources_with_netbeans.html">Building JME3 from the sources with NetBeans</a></div></li></ul></div> |
|
||||||
|
<h1><a>Building jMonkeyEngine 3 from the Sources</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
We recommend downloading the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/downloads/list"><param name="text" value="<html><u>jMonkeyEngine SDK</u></html>"><param name="textColor" value="blue"></object> - but of course you can also build the jMonkeyEngine yourself from the sources. In this case, you need the <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://subversion.tigris.org"><param name="text" value="<html><u>Subversion</u></html>"><param name="textColor" value="blue"></object> file version system installed (svn). |
||||||
|
|
||||||
|
</p> |
||||||
|
<ol> |
||||||
|
<li><div> <strong>Checkout:</strong> Checkout the Subversion repository. <pre>svn checkout http://jmonkeyengine.googlecode.com/svn/trunk/engine jme3</pre> |
||||||
|
</div> |
||||||
|
<ul> |
||||||
|
<li><div> You can leave login and password empty</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li><div> <strong>Build:</strong> Execute <code>ant jar</code></div> |
||||||
|
<ul> |
||||||
|
<li><div> This compiles the JAR files in <code>dist/libs/*</code></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li><div> <strong>Javadoc:</strong> Execute <code>ant javadoc</code> </div> |
||||||
|
<ul> |
||||||
|
<li><div> This generates javadocs in the <code>dist/javadoc</code> directory.</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li><div> <strong>Run:</strong> Execute <code>ant run</code></div> |
||||||
|
<ul> |
||||||
|
<li><div> This runs the TestChooser where you can browse examples.</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li><div> <strong>Use:</strong> Create a Java SE project and place all JARs from the <code>dist/lib</code> directory on the classpath.</div> |
||||||
|
<ul> |
||||||
|
<li><div> You can now extend your first game from <code>com.jme3.app.SimpleApplication</code>. </div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
<hr /> |
||||||
|
|
||||||
|
<p> |
||||||
|
Learn more about: |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> <a href="/com/jme3/gde/core/docs/jme3/simpleapplication_from_the_commandline.html">Setting up JME3 on the commandline (generic)</a>.</div> |
||||||
|
</li> |
||||||
|
<li><div> <a href="/com/jme3/gde/core/docs/jme3/build_jme3_sources_with_netbeans.html">Building JME3 from the sources with NetBeans</a> </div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:build_from_sources?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:build_from_sources?do=export_xhtmlbody">view online version</a></em></p> |
@ -1,2 +1,78 @@ |
|||||||
<h1><a>jMonkeyEngine3 Supported File Types</a></h1><div></div><h2><a>jMonkeyEngine3 File Formats</a></h2><div><div><table><tr><th>Suffix</th><th>Usage</th><th>Learn more</th></tr><tr><td>.j3o</td><td>Binary 3D model or scene. At the latest from the Beta release of your game on, you should convert all models to .j3o format. <br/> During alpha and earlier development phases (when models still change a lot) you can alternatively load OgreXML/OBJ models directly.</td><td><a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">Model Loader and Viewer</a></td></tr><tr><td>.j3m</td><td>A custom Material. You can create a .j3m file to store a Material configuration for a Geometry (e.g. 3D model).</td><td><a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> <br/> <a href="/com/jme3/gde/core/docs/sdk/material_editing.html">Material Editing</a></td></tr><tr><td>.j3md</td><td>A Material definition. These are pre-defined templates for shader-based Materials. <br/> Each custom .j3m Material is based on a material definition. Advanced users can create their own material definitions.</td><td><a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a></td></tr><tr><td>.j3f</td><td>A custom post-processor filter configuration. You can create a .j3f file to store a FilterPostProcessor with a set of preconfigured filters.</td><td><a href="/com/jme3/gde/core/docs/sdk/filters.html">Filters</a> <br/> <a href="/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html">Effects Overview</a></td></tr></table></div></div><h2><a>Supported External File Types</a></h2><div><div><table><tr><th>File Suffix</th><th>Type</th><th>Description</th></tr><tr><td>.mesh.xml, .meshxml</td><td>3D model</td><td>Ogre Mesh <acronym title="Extensible Markup Language">XML</acronym></td></tr><tr><td>.scene</td><td>3D scene</td><td>Ogre DotScene</td></tr><tr><td>.OBJ, .MTL</td><td>3D model</td><td>Wavefront</td></tr><tr><td>.blend</td><td>3D model</td><td>Blender version 2.49 or 2.5x</td></tr><tr><td>.<acronym title="Joint Photographics Experts Group">JPG</acronym>, .<acronym title="Portable Network Graphics">PNG</acronym>, .<acronym title="Graphics Interchange Format">GIF</acronym></td><td>image</td><td>Textures, icons</td></tr><tr><td>.DDS</td><td>image</td><td>Direct Draw Surface texture</td></tr><tr><td>.HDR</td><td>image</td><td>High Dynamic Range texture</td></tr><tr><td>.TGA</td><td>image</td><td>Targa Image File texture</td></tr><tr><td>.PFM</td><td>image</td><td>Portable Float Map texture</td></tr><tr><td>.fnt</td><td>bitmap font</td><td>AngelCode font for <acronym title="Graphical User Interface">GUI</acronym> and HUD</td></tr><tr><td>.WAV</td><td>audio</td><td>Wave music and sounds</td></tr><tr><td>.OGG</td><td>audio</td><td>OGG Vorbis music and sounds</td></tr></table></div></div> |
|
||||||
|
<h1><a>jMonkeyEngine3 Supported File Types</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>jMonkeyEngine3 File Formats</a></h2> |
||||||
|
<div> |
||||||
|
<div><table> |
||||||
|
<tr> |
||||||
|
<th>Suffix</th><th>Usage</th><th>Learn more</th> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.j3o</td><td>Binary 3D model or scene. At the latest from the Beta release of your game on, you should convert all models to .j3o format. <br/> |
||||||
|
During alpha and earlier development phases (when models still change a lot) you can alternatively load OgreXML/OBJ models directly.</td><td><a href="/com/jme3/gde/core/docs/sdk/model_loader_and_viewer.html">Model Loader and Viewer</a> </td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.j3m</td><td>A custom Material. You can create a .j3m file to store a Material configuration for a Geometry (e.g. 3D model).</td><td><a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> <br/> |
||||||
|
<a href="/com/jme3/gde/core/docs/sdk/material_editing.html">Material Editing</a> </td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.j3md</td><td>A Material definition. These are pre-defined templates for shader-based Materials. <br/> |
||||||
|
Each custom .j3m Material is based on a material definition. Advanced users can create their own material definitions. </td><td> <a href="/com/jme3/gde/core/docs/jme3/advanced/materials_overview.html">Materials Overview</a> </td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.j3f</td><td>A custom post-processor filter configuration. You can create a .j3f file to store a FilterPostProcessor with a set of preconfigured filters. </td><td> <a href="/com/jme3/gde/core/docs/sdk/filters.html">Filters</a> <br/> |
||||||
|
<a href="/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html">Effects Overview</a> </td> |
||||||
|
</tr> |
||||||
|
</table></div> |
||||||
|
<!-- EDIT1 TABLE [93-1068] --> |
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Supported External File Types</a></h2> |
||||||
|
<div> |
||||||
|
<div><table> |
||||||
|
<tr> |
||||||
|
<th>File Suffix</th><th>Type</th><th>Description</th> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.mesh.xml, .meshxml</td><td>3D model</td><td>Ogre Mesh <acronym title="Extensible Markup Language">XML</acronym> </td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.scene</td><td>3D scene</td><td>Ogre DotScene </td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.OBJ, .MTL</td><td>3D model</td><td>Wavefront</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.blend</td><td>3D model</td><td>Blender version 2.49 or 2.5x</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.<acronym title="Joint Photographics Experts Group">JPG</acronym>, .<acronym title="Portable Network Graphics">PNG</acronym>, .<acronym title="Graphics Interchange Format">GIF</acronym></td><td>image</td><td>Textures, icons</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.DDS</td><td>image</td><td>Direct Draw Surface texture</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.HDR</td><td>image</td><td>High Dynamic Range texture</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.TGA</td><td>image</td><td>Targa Image File texture</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.PFM</td><td>image</td><td>Portable Float Map texture</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.fnt</td><td>bitmap font</td><td>AngelCode font for <acronym title="Graphical User Interface">GUI</acronym> and HUD</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.WAV</td><td>audio</td><td>Wave music and sounds</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>.OGG</td><td>audio</td><td>OGG Vorbis music and sounds</td> |
||||||
|
</tr> |
||||||
|
</table></div> |
||||||
|
<!-- EDIT2 TABLE [1113-1628] --> |
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:intermediate:file_types?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/jme3:intermediate:file_types?do=export_xhtmlbody">view online version</a></em></p> |
@ -0,0 +1,69 @@ |
|||||||
|
|
||||||
|
<h1><a>Using Blender as a Intermediator Between 3dMax and the jMonkeyEngine SDK</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
The jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> supports .blend files and can convert them to jMonkeyEngine's .j3o format. This means you can use Blender to convert, for example, a 3dMax file to .j3o format. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Importing the .3ds file to Blender</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
I'm using the blender 2.59 at this tutorial, but if you blender 2.49b, no problem ;). |
||||||
|
After you saved your .3ds file in 3dmax, open the blender, delete the default cube, |
||||||
|
and import your .3ds file via File—→Import—–>3D Studio. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<img src="/wiki/lib/exe/fetch.php"> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Saving the .blend file</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Now save your .blend file so you can load it into the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym>. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<img src="/wiki/lib/exe/fetch.php"> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Importing the .blend file to the SDK by using the ModelImporter and BlenderSupport plugins</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
Click on Import Model button and then click on Open Model button to open the .blend file. Click next, select the checkbox to import a copy from .blend file, and click finish. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<img src="/wiki/lib/exe/fetch.php"> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Edit your model in SceneComposer and "VOILA"</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
As you can see, the .blend model was automatically converted to .j3o binary format. Now, you are able to edit it in SceneComposer ;D. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<img src="/wiki/lib/exe/fetch.php"> |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:3ds_to_blender_to_jmp?do=export_xhtmlbody">view online version</a></em></p> |
@ -1,2 +1,30 @@ |
|||||||
<h1><a>Creating a model importer</a></h1><div><ol><li><div>Create plugin</div></li><li><div>Add importer jar file (wrap jar file)</div></li><li><div>Add filetype (Template)</div></li><li><div>Change DataObject to extend SpatialAssetDataObject</div></li><li><div>Implement loadAsset method in DataObject (if necessary, most model formats should load normally via the loader)</div></li><li><div>Create AssetManagerConfigurator \</div></li></ol><p>See also:</p><ul><li><div><a href="/com/jme3/gde/core/docs/sdk/development/projects_assets.html">Projects and Assets</a></div></li><li><div><object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://platform.netbeans.org/tutorials/nbm-filetype.html"><param name="text" value="<html><u>http://platform.netbeans.org/tutorials/nbm-filetype.html</u></html>"><param name="textColor" value="blue"></object></div></li></ul></div> |
|
||||||
|
<h1><a>Creating a model importer</a></h1> |
||||||
|
<div> |
||||||
|
<ol> |
||||||
|
<li><div> Create plugin</div> |
||||||
|
</li> |
||||||
|
<li><div> Add importer jar file (wrap jar file)</div> |
||||||
|
</li> |
||||||
|
<li><div> Add filetype (Template)</div> |
||||||
|
</li> |
||||||
|
<li><div> Change DataObject to extend SpatialAssetDataObject</div> |
||||||
|
</li> |
||||||
|
<li><div> Implement loadAsset method in DataObject (if necessary, most model formats should load normally via the loader)</div> |
||||||
|
</li> |
||||||
|
<li><div> Create AssetManagerConfigurator \</div> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<p> |
||||||
|
See also: |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> <a href="/com/jme3/gde/core/docs/sdk/development/projects_assets.html">Projects and Assets</a></div> |
||||||
|
</li> |
||||||
|
<li><div> <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://platform.netbeans.org/tutorials/nbm-filetype.html"><param name="text" value="<html><u>http://platform.netbeans.org/tutorials/nbm-filetype.html</u></html>"><param name="textColor" value="blue"></object></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:development:model_loader?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:development:model_loader?do=export_xhtmlbody">view online version</a></em></p> |
@ -0,0 +1,43 @@ |
|||||||
|
|
||||||
|
<h1><a>jMonkeyEngine SDK Log Files</a></h1> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
You find the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> log file in <code>/dev/var/log/messages.log</code> in the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> preferences folder. You can learn the location of the preferences folder in the “About” screen of the jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> under the label <strong>Userdir</strong>. |
||||||
|
|
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li><div> Windows: <code>C:\Documents and Settings\YOUR_NAME\.jmonkeyplatform\</code></div> |
||||||
|
</li> |
||||||
|
<li><div> Linux: <code>/home/YOUR_NAME/.jmonkeyplatform/</code></div> |
||||||
|
</li> |
||||||
|
<li><div> Mac <acronym title="Operating System">OS</acronym>: <code>/Users/YOUR_NAME/Library/Application Support/jmonkeyplatform/</code></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<p> |
||||||
|
|
||||||
|
The message log contains all paths and <a href="/com/jme3/gde/core/docs/jme3/advanced/read_graphic_card_capabilites.html">capabilities</a> used in your development system, and also warnings, e.g. if a plugin crashed. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h2><a>Example Log</a></h2> |
||||||
|
<div> |
||||||
|
<pre>>Log Session: Saturday, September 24, 2011 10:45:30 AM CEST |
||||||
|
>System Info: |
||||||
|
Product Version = jMonkeyPlatform Alpha-4 |
||||||
|
Operating System = Mac OS X version 10.6.8 running on i386 |
||||||
|
Java; VM; Vendor = 1.6.0_26; Java HotSpot(TM) Client VM 20.1-b02-384; Apple Inc. |
||||||
|
Runtime = Java(TM) SE Runtime Environment 1.6.0_26-b03-384-10M3425 |
||||||
|
Java Home = /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home |
||||||
|
System Locale; Encoding = de_DE (jmonkeyplatform); MacRoman |
||||||
|
Home Directory = /Users/joemonkey |
||||||
|
Current Directory = / |
||||||
|
User Directory = /Users/joemonkey/Library/Application Support/jmonkeyplatform/dev |
||||||
|
Installation = /Applications/jmonkeyplatform.app/Contents/Resources/jmonkeyplatform/jmonkeyplatform |
||||||
|
...</pre> |
||||||
|
|
||||||
|
</div> |
||||||
|
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:log_files?do=export_xhtmlbody">view online version</a></em></p> |
@ -1,2 +1,31 @@ |
|||||||
<h2><a>Troubleshooting jMonkeyEngine3 SDK</a></h2><div></div><h3><a>Specifying the JDK location</a></h3><div><p>If jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> cannot find a valid <acronym title="Java Development Kit">JDK</acronym> although you have it installed you have to specify the location manually.</p><p>To do that edit the file <code>jmonkeyplatform.conf</code> in the <code>etc</code> directory of your jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> installation location. Mac users have to right-click the application and select "Show package contents" and then navigate to <code>Contents/Resources/jmonkeyplatform</code>.</p></div><h3><a>Known Issues</a></h3><div><p>For a list of known issues and possible workarounds see the following link: <object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/issues/list?can=2&q=label%3AProduct-Platform+Type%3DDefect+&colspec=ID+Type+Status+Component+Priority+Product+Milestone+Owner+Summary&cells=tiles"><param name="text" value="<html><u>List of known issues on googlecode</u></html>"><param name="textColor" value="blue"></object></p></div> |
|
||||||
|
<h2><a>Troubleshooting jMonkeyEngine3 SDK</a></h2> |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>Specifying the JDK location</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
If jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> cannot find a valid <acronym title="Java Development Kit">JDK</acronym> although you have it installed you have to specify the location manually. |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
To do that edit the file <code>jmonkeyplatform.conf</code> in the <code>etc</code> directory of your jMonkeyEngine <acronym title="Software Development Kit">SDK</acronym> installation location. |
||||||
|
Mac users have to right-click the application and select "Show package contents" and then navigate to <code>Contents/Resources/jmonkeyplatform</code>. |
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<h3><a>Known Issues</a></h3> |
||||||
|
<div> |
||||||
|
|
||||||
|
<p> |
||||||
|
For a list of known issues and possible workarounds see the following link: |
||||||
|
<object classid="java:org.netbeans.modules.javahelp.BrowserDisplayer"><param name="content" value="http://code.google.com/p/jmonkeyengine/issues/list?can=2&q=label%3AProduct-Platform+Type%3DDefect+&colspec=ID+Type+Status+Component+Priority+Product+Milestone+Owner+Summary&cells=tiles"><param name="text" value="<html><u>List of known issues on googlecode</u></html>"><param name="textColor" value="blue"></object> |
||||||
|
|
||||||
|
</p> |
||||||
|
|
||||||
|
</div> |
||||||
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:troubleshooting?do=export_xhtmlbody">view online version</a></em></p> |
<p><em><a href="http://jmonkeyengine.org/wiki/doku.php/sdk:troubleshooting?do=export_xhtmlbody">view online version</a></em></p> |