3DViewer: Better 3D for JavaFX

JavaFX has long had basic 3D capabilities, although you might not guess it as some outdated package descriptions still only speak of “two-dimensional geometry.” Oracle offers an online tutorial for JavaFX 3D, and JavaFX by Example devotes a chapter to it. Here’s a brief overview:

That’s a solid basis but no more than that. Important features for practical applications are missing, such as skeletal animation and importing standard 3D model files. As a result, JavaFX has been largely ignored by the 3D programming community. If you search for “Java 3D” nearly all hits will refer to the powerful but ancient Java 3D API, long abandoned by Oracle and now supported by volunteers (for OpenGL only).

Introducing 3DViewer

When I talked on Twitter about importing Wavefront OBJ files into a JavaFX MeshView, the friendly and helpful JavaFX 3D account pointed me to a set of JavaFX 3D extensions by the Oracle team itself, created for demos at the JavaOne Keynotes in 2011–13. These extensions never left experimental state before the authors were let go, amidst the ongoing reductions of Oracle’s JavaFX investment.

As a result they don’t come with any official binary build. However, they are still available with the OpenJFX source code, as part of the 3DViewer demo application. That’s a subdirectory within the OpenJFX 10 project on Github. I couldn’t find a way to download just the 3DViewer tree without a Git client, but you can download the whole project as a ZIP file and extract apps/samples/3DViewer.

3DViewer comes with a Gradle project for IntelliJ IDEA and a NetBeans project, but the build is straightforward and requires no external dependencies. I simply did an IntelliJ source import, marked the obvious resource and test directories, and the project compiled fine. Well, except for 100 warnings about raw types, unchecked conversions etc., mostly related to Java’s daft generics. The authors understandably hadn’t bothered to insert 100 warning suppression annotations for an experimental project.

Sample with FreeCiv & Blender

3DViewer is a JavaFX application for showing 3D models loaded from disk in various formats, with lots of display options. To try it out you really need your own 3D models as the provided files under main/resources are pretty boring – just variations on “Drop 3D File Here” with an arrow – while the ones under test/resources are intended for partially testing file import/export, and fail to load in the viewer application.

What if you don’t have any 3D models handy? There are various free compilation sites, but one unlikely source of high-quality models is FreeCiv. The desktop game uses tiny 2D sprites but those were created from surprisingly detailed Blender 3D models which are thoughtfully included in the source code download, under data/graphics/cimpletoon. FreeCiv Web contains a less detailed alternative set of Blender models, by the way.

Now just load any model into Blender and export it to Wavefront OBJ format. This should work fine, although you may have to delete helper objects in Blender that were not intended for output, such as giant hooves in models with horses! 3DViewer’s camera setup is such that I had to use one of the smaller FreeCiv Web models, as the original FreeCiv models were too large to show properly. (They did load correctly, though.) So here’s an example of a simple but serviceable galley.

Galley Sample

Note: FreeCiv Web also has a number of complex models in OpenGL binary glTF (.glb) format. 3DViewer cannot read them, and there is currently no good importer for Blender. But if you’re on Windows 10 you’re all set: Microsoft’s free 3DBuilder app can correctly import GLB files and export them as OBJ files.

3DViewer Library Features

The 3DViewer application is nice but we’re more interested in the new JavaFX 3D classes that come with it, so here’s a brief overview. I’m only listing the main classes providing new functionality; they often have their own sets of helper classes.

  • Advanced MeshesPolygonMesh(View) for meshes with arbitrary polygons instead of triangles, SkinningMesh for skeletal animation, and SubdivisionMesh for Catmull–Clark surface smoothing.
  • ExportersFXMLExporter and JavaSourceExporter export MeshView scenes to FXML and Java source code, respectively.
  • ImportersImporter3D is a static utility class that dispatches to one of four classes implementing Importer.
  • Map ConversionHeight2NormalConverter converts height maps to normal maps. This class is only used by its own separate GUI demo application.
  • Primitives — Various geometric primitives such as vectors and transformation support the rest of the library.

That’s a very nice set of extensions to make JavaFX 3D usable in practice. Keep in mind that this code is experimental, so documentation is somewhat lacking and implementation may be incomplete or buggy. The one functionality I did try extensively was OBJ import, and that worked fine.

The features bundled with 3DViewer would make a great addition to the official JavaFX distribution, once the code is cleaned up and tested. And now that Oracle plans to hand over JavaFX to the community that’s a realistic possibility, too.

4 thoughts on “3DViewer: Better 3D for JavaFX”

Leave a Reply