The Jme3-utilities Project contains Java packages and assets, developed for sgold's jMonkeyEngine projects, which might prove useful in similar projects. It contains 8 sub-projects:
- heart: the
jme3-utilities-heart
library of core classes - SkyControl: the
SkyControl
library for sky simulation - moon-ccbysa: assets for a realistic Moon in
SkyControl
- tests: demos, examples, and test software
- textures: generate textures used by
jme3-utilities-heart
andSkyControl
- ui: the
jme3-utilities-ui
library for building user interfaces - nifty: the
jme3-utilities-nifty
library for using NiftyGUI user interfaces with jMonkeyEngine - x: the
jme3-utilities-x
library of experimental software
The jme3-utilities-debug
library, formerly a sub-project, has merged
into the jme3-utilities-heart
library.
The Minie
library, formerly a sub-project, is now a separate project
at GitHub.
The Wes
library, formerly a sub-project, is now a separate project
at GitHub.
Summary of SkyControl features:
- sun, moon, stars, horizon haze, and up to 6 cloud layers
- compatible with static backgrounds such as cube maps
- high resolution textures are provided -- or customize with your own textures
- compatible with effects such as
SimpleWater
, shadows, bloom, and cartoon edges - continuous and reversible motion and blending of cloud layers
- option to foreshorten clouds near the horizon
- continuous and reversible motion of sun, moon, and stars based on time of day
- updater to synchronize lighting and shadows with sun, moon, and clouds
- continuous scaling of sun, moon, and clouds
- option for continuously variable phase of the moon
- demonstration apps and online tutorial provided
- complete source code provided under FreeBSD license
- Downloads
- Conventions
- History
- How to install the SDK and the Jme3-utilities Project
- How to add SkyControl to an existing game
- External links
- Acknowledgments
Recent releases can be downloaded from GitHub.
Maven artifacts are available from JFrog Bintray.
Since the Jme3-utilities Project is not associated with an Internet domain,
package names generally begin with jme3utilities
. Packages copied from
jMonkeyEngine and the BVH Retarget Project,
however, retain their original names, which began with com.jme3
.
The source code remains compatible with JDK 7.
World coordinate system:
- the
+X
axis points toward the northern horizon - the
+Y
axis points up (toward the zenith) - the
+Z
axis points toward the eastern horizon
Since September 2015, the Jme3-utilities Project has been hosted at GitHub.
From November 2013 to September 2015, it was hosted at Google Code.
Old (2014) versions of the Jme3-utilities Project can still be found in the jMonkeyEngine-Contributions Project.
The evolution of each sub-project is chronicled in its release notes:
The master
branch of the jme3-utilities repository targets
Version 3.2.2 of jMonkeyEngine. You are welcome to use the Engine
without also using the SDK, but I use the SDK, and the following
installation instructions assume you will too.
The hardware and software requirements of the SDK are documented on the JME wiki.
- Download a jMonkeyEngine 3.2 SDK from GitHub.
- Install the SDK, which includes:
- the engine itself,
- an integrated development environment (IDE) based on NetBeans,
- various plugins, and
- the Blender 3D application.
- To open the Jme3-utilities Project in the IDE (or NetBeans), you will need the
Gradle Support
plugin. Download and install it before proceeding. If this plugin isn't shown in the IDE's "Plugins" tool, you can download it from GitHub.
Clone the jme3-utilities repository using Git:
- Open the Clone wizard in the IDE:
- Menu bar -> "Team" -> "Remote" -> "Clone..."
- For "Repository URL:" specify
https://github.com/stephengold/jme3-utilities.git
- Clear the "User:" and "Password:" text boxes.
- For "Clone into:" specify a writable folder (on a local filesystem) which doesn't already contain "jme3-utilities".
- Click on the "Next >" button.
- Make sure the "master" remote branch is checked.
- Click on the "Next >" button again.
- Make sure the Checkout Branch is set to "master".
- Make sure the "Scan for NetBeans Projects after Clone" box is checked.
- Click on the "Finish" button.
- When the "Clone Complete" dialog appears, click on the "Open Project..." button.
- Expand the root project node to reveal the 10 sub-projects.
- To start with, I recommend opening 4 sub-projects: "heart", "SkyControl", "tests", and "textures". Select them using control-click, then click on the "Open" button.
- There will be errors in the "textures" sub-project. However, the build task should resolve them.
- In the "Projects" window, right-click on the "tests" sub-project to select it.
- Select "Build".
SkyControl is a reusable sky simulation for jMonkeyEngine games.
Adding it to an existing JME3 project should be a simple 6-step process:
- Add jme3-utilities JARs to the classpath.
- Disable any existing sky which might interfere with SkyControl.
- Add a
SkyControl
instance to some node in the scene graph. - Configure the
SkyControl
instance. - Enable the
SkyControl
instance. - Test and tune as necessary.
To demonstrate this process, we'll apply it to BasicGame
and then to
CubeMapExample
, a more sophisticated application. I encourage you to
follow along in your development environment.
You'll need:
- A development system with the JME3 SDK installed.
- A clean build of the jme3-utilities JARs, either downloaded from GitHub or built yourself.
Instantiate a BasicGame Project:
- Open the "New Project" wizard in the IDE:
- Menu bar -> "File" -> "New Project..."
- Under "Categories:" select "JME3".
- Under "Projects:" select "BasicGame".
- Click on the "Next >" button.
- For "Project Location:" specify a writable folder (on a local filesystem) which doesn't already contain "BasicGame".
- Click on the "Finish" button.
If you're unfamiliar with BasicGame, you may wish to run it (and/or examine the source code) to see how it works before modifying it.
- To rotate the camera, move the mouse.
- The W/A/S/D/Q/Z keys translate (move) the camera.
- To exit, press the Esc key.
In the following instructions, "0.0.0" indicates a version number.
Open the project's properties in the IDE:
- Right-click on the BasicGame project (not its assets) in the "Projects" window.
- Select "Properties to open the "Project Properties" dialog.
- Under "Categories:" select "Libraries".
- Click on the "Compile" tab.
- Add the
jme3-utilities-heart
class JAR:- Click on the "Add JAR/Folder" button.
- Navigate to the "jme3-utilities" project folder.
- Open the "heart" sub-project folder.
- Navigate to the "build/libs" folder.
- Select the "jme3-utilities-heart-0.0.0.jar" file.
- Click on the "Open" button.
- (optional) Add JARs for javadoc and sources:
- Click on the "Edit" button.
- Click on the "Browse..." button to the right of "Javadoc:"
- Select the "jme3-utilities-heart-0.0.0-javadoc.jar" file.
- Click on the "Open" button.
- Click on the "Browse..." button to the right of "Sources:"
- Select the "jme3-utilities-heart-0.0.0-sources.jar" file.
- Click on the "Open" button again.
- Click on the "OK" button to close the "Edit Jar Reference dialog.
- Add the "SkyControl" class JAR:
- Click on the "Add JAR/Folder" button.
- Navigate to the "jme3-utilities" project folder.
- Open the "SkyControl" sub-project folder.
- Navigate to the "build/libs" folder.
- Select the "SkyControl-0.0.0.jar" file.
- Click on the "Open" button.
- (optional) Add JARs for javadoc and sources:
- Click on the "Edit" button.
- Click on the "Browse..." button to the right of "Javadoc:"
- Select the "SkyControl-0.0.0-javadoc.jar" file.
- Click on the "Open" button.
- Click on the "Browse..." button to the right of "Sources:"
- Select the "SkyControl-0.0.0-sources.jar" file.
- Click on the "Open" button again.
- Click on the "OK" button to close the "Edit Jar Reference dialog.
- (optional) Add the "moon-ccbysa" class JAR:
- Click on the "Add JAR/Folder" button.
- Navigate to the "jme3-utilities" project folder.
- Open the "moon-cc-by-sa" sub-project folder.
- Navigate to the "build/libs" folder.
- Select the "moon-ccbysa-0.0.0.jar" file.
- Click on the "Open" button.
- Click on the "OK" button to exit the "Project Properties" dialog.
Since BasicGame has no sky -- just the default (black) viewport background -- there is nothing to disable.
The scene graph of BasicGame has only one node, the root node. The root node is
typically a good place to add SkyControl
.
-
Open the "Main.java" source file in the IDE:
- In the "Projects" window, expand the BasicGame project node.
- Expand the "Source Packages" node under the BasicGame project.
- Expand the "mygame" package under "Source Packages".
- Select "Main.java" file under the "mygame" package.
- Double-click to open the file.
-
In the import section of "Main.java", add the following code:
import jme3utilities.sky.SkyControl; import jme3utilities.sky.StarsOption;
-
Scroll down to the
simpleInitApp()
method and insert the following code just before the final close-brace:SkyControl sc = new SkyControl(assetManager, cam, 0.9f, StarsOption.Cube, true); rootNode.addControl(sc);
The parameters of the constructor are documented in the Javadoc for the
SkyControl
class.
By default, SkyControl
simulates midnight on March 21st in Wiltshire, England,
with no clouds and a full moon. Instead, let's configure 6 a.m. on February 10th
in Sunnyvale, California with dense clouds:
-
In the import section of "Main.java", add the following code:
import com.jme3.math.FastMath; import java.util.Calendar; import jme3utilities.sky.SunAndStars;
-
In
simpleInitApp()
, insert the following code just before the final close brace:SunAndStars sns = sc.getSunAndStars(); sns.setHour(6f); sns.setObserverLatitude(37.4046f * FastMath.DEG_TO_RAD); sns.setSolarLongitude(Calendar.FEBRUARY, 10); sc.setCloudiness(1f);
Other configuration methods are documented in the Javadoc for the SkyControl
,
SkyControlCore
, SunAndStars
, CloudLayer
, and Updater
classes.
If you run the modified BasicGame at this point, you'll find no visible change.
Unlike most JME3 controls, SkyControl
instantiates in a disabled state. In order
to see the sky, you must enable the control:
-
In simpleInitApp(), insert the following code just before the final close-brace:
sc.setEnabled(true);
To test the modified BasicGame, right-click in the "Main.java" editor window and select "Run File (Shift+F6)".
Sometimes you'll want to combine SkyControl with other sky elements. The Jme3-utilities Project includes CubeMapExample, a slightly more sophisticated application than BasicGame. CubeMapExample includes a cube-mapped sky, lit terrain, and multiple light sources. In this section, you'll see how SkyControl can be used to add sun, moon, and clouds to CubeMapExample.
In the "Projects" window of the IDE, expand the "tests" sub-project node and the "jme3utilities.sky.test" source package. Open the "CubeMapExample.java" file to examine the code and run it.
- To rotate the camera, drag with the left mouse button.
- The W/A/S/D/Q/Z keys translate (move) the camera.
- To exit, press the Esc key.
Since CubeMapExample is part of the Jme3-utilities Project, there's no need to add anything to the classpath. And since we plan to use the existing cube map, there's nothing to remove.
Both SkyFactory and SkyControl add geometries to Bucket.Sky. In the absence of a custom GeometryComparator, geometries in this bucket are rendered in scene graph order. Since the cube map is opaque, we want to SkyControl to add its geometries after the sky cube in the scene graph.
-
In the import section of "CubeMapExample.java", add the following code:
import jme3utilities.sky.SkyControl; import jme3utilities.sky.StarsOption;
-
Scroll down to the
initializeSky()
method and insert the following code just before the final close-brace:SkyControl sc = new SkyControl(assetManager, cam, 0.8f, StarsOption.TopDome, true); rootNode.addControl(sc);
For now, we've turned star motion off, since that simplifies things. The lower value (0.8) for cloud flattening will make it easier to compensate for the scene's low horizon.
-
It's important to disable the SkyControl's built-in star maps so that the cube map's stars will be visible at night:
sc.clearStarMaps();
-
Adjust the cloudiness so that clouds will be visible:
sc.setCloudiness(0.8f);
In initializeSky()
, insert the following code just before the final close-brace:
sc.setEnabled(true);
At this point, the application should run successfully. (Look! A cloud!) However, for the best result, it needs some tuning.
-
To lower the edge of the cloud dome so that it's hidden by the terrain, add the following code:
sc.setCloudsYOffset(0.4f);
-
To see the scene in daylight, add this:
sc.getSunAndStars().setHour(12f);
-
To synchronize the lights with SkyControl, add this to the import section:
import com.jme3.light.Light;
and this to the end of the
initializeSky()
method:for (Light light : rootNode.getLocalLightList()) { if (light.getName().equals("ambient")) { sc.getUpdater().setAmbientLight((AmbientLight) light); } else if (light.getName().equals("main")) { sc.getUpdater().setMainLight((DirectionalLight) light); } }
The uneven shading of the level terrain is due to sunlight coming in at a low angle. Since it's noon, the easiest way to raise the sun's elevation is to decrease the observer's latitude. Also, the terrain is too dark. Try, for instance:
sc.getSunAndStars().setObserverLatitude(0.2f);
sc.getUpdater().setMainMultiplier(2f);
The sun looks like a boring white disc in the southern sky. For a more dazzling sun, apply a bloom filter to the viewport:
import com.jme3.post.filters.BloomFilter;
import jme3utilities.Misc;
...
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
bloom.setBlurScale(2.5f);
bloom.setExposurePower(1f);
int numSamples = settings.getSamples();
Misc.getFpp(viewPort, assetManager, numSamples).addFilter(bloom);
sc.getUpdater().addBloomFilter(bloom);
To add star motion, it's not sufficient simply to change the control's constructor from
SkyControl sc = new SkyControl(assetManager, cam, 0.8f, StarsOption.TopDome, true);
to
SkyControl sc = new SkyControl(assetManager, cam, 0.8f, StarsOption.Cube, true);
It's also necessary to rotate the cube map to match SkyControl's notions of time
and space. To achieve this, override the application's simpleUpdate()
method:
@Override
public void simpleUpdate(float unused) {
Spatial starMap = rootNode.getChild("Sky");
SkyControl sc = rootNode.getControl(SkyControl.class);
sc.getSunAndStars().orientEquatorialSky(starMap, true);
}
To simulate the passage of time, we need state and a mechanism to update it. The jme3utilities.TimeOfDay appstate fills this need.
-
Import the class:
import jme3utilities.TimeOfDay;
-
Declare a field in
CubeMapExample
:TimeOfDay timeOfDay;
-
Initialize and attach it in
simpleInitApp()
:timeOfDay = new TimeOfDay(19f); stateManager.attach(timeOfDay); timeOfDay.setRate(1000f);
All that remains is to update the control.
-
Add 2 lines to
simpleUpdate()
, right before the invocation oforientExternalSky()
:float hour = timeOfDay.hour(); sc.getSunAndStars().setHour(hour);
To see how some of the other features of SkyControl can be used, you may wish to study "TestSkyControl.java" in the "tests" sub-project. The easiest way to run TestSkyControl is to right-click on the "tests" sub-project and select "Tasks" -> "run" -> "runTestSkyControl".
- November 2013 SkyControl demo video
- January 2014 SkyControl update video
- A maze game that uses the Jme3-utilities libraries.
- A flight simulation game that uses SkyControl.
Like most projects, the Jme3-utilities Project builds on the work of many who have gone before. I therefore acknowledge the following artists and software developers:
- Cris (aka "t0neg0d") for creating SkyDome (which provided both an inspiration and a starting point for SkyControl) and also for encouraging me to run with it ... thank you yet again!
- Paul Speed, for helpful insights which got me unstuck during debugging
- Rémy Bouquet (aka "nehon") for many helpful insights
- Alexandr Brui (aka "javasabr") for a solving a problem with the
de-serialization of
SkyControl
- the brave souls who volunteered to be alpha testers for SkyControl, including:
- Davis Rollman
- "Lockhead"
- Jonatan Dahl
- Mindaugas (aka "eraslt")
- Thomas Kluge
- "pixelapp"
- Roger (aka "stenb")
- the beta testers for SkyControl, including:
- "madjack"
- Benjamin D.
- "Fissll"
- Davis Rollman
- users who found and reported bugs in later versions:
- Anton Starastsin (aka "Antonystar")
- the creators of (and contributors to) the following software:
- Adobe Photoshop Elements
- the Ant and Gradle build tools
- the Blender 3-D animation suite
- the FindBugs source-code analyzer
- Gimp, the GNU Image Manipulation Program
- the Git and Subversion revision-control systems
- the Google Chrome web browser
- Guava core libraries for Java
- the Java compiler, standard doclet, and runtime environment
- the JCommander Java framework
- jMonkeyEngine and the jME3 Software Development Kit
- LWJGL, the Lightweight Java Game Library
- the Markdown document conversion tool
- Microsoft Windows
- the NetBeans integrated development environment
- the Nifty graphical user interface library
- Open Broadcaster Software Studio
- the PMD source-code analyzer
- the RealWorld Cursor Editor
- Alex Peterson's Spacescape tool
- the WinMerge differencing and merging tool
Many of SkyControl's assets were based on the works of others who licensed their works under liberal terms or contributed them to the public domain. For this I thank:
- Cris (aka "t0neg0d")
- Jacques Descloitres, MODIS Rapid Response Team, NASA/GSFC
- Tom Ruen
I am grateful to JFrog, Google, and Github for providing free hosting for the Jme3-utilities Project and many other open-source projects.
I'm also grateful to Quinn (for lending me one of her microphones) and finally my dear Holly, for keeping me sane.
If I've misattributed anything or left anyone out, please let me know so I can correct the situation: [email protected]