More about the math.

After being asked about it a few times I thought I should expound a bit more about Ardor3D's math library here.

As I mentioned, our math package currently uses double precision. This includes our Vector, Quaternion and Matrix classes. Actual mesh data is of course not part of this, nor is ColorRGBA. The reason for our move to use double is simple: current customers of Ardor Labs want higher accuracy. (Yes, we want to make money from our work and we want others to as well.)

Having double precision camera matrices and transforms helps a lot when dealing with coordinate systems needing more than 8 places (for example, if you want to model a section of the earth or conversely, something happening at the micro-scale.) This is particularly true about the camera control matrix math where even small inaccuracies cause noticeable camera wobble.

Using double precision means a little more memory but since this is only transforms (15 values in the current Transform object), we're talking about 60 more bytes or so per Transform in your scene graph -- probably not a deal breaker.

The other perhaps more legitimate question is performance. As I understand it, floating point calculations on a modern CPU (Pentium or higher) are done at 80bits or more regardless of using Java's 64bit double or 32 bit float. Where speed enters the picture then is how many math primitives you can fit into cache or RAM. The question is whether that matters much with today's current cache and RAM sizes? Will you have tens of thousands of different matrices you are needing to multiply out in fast succession? Sure it is possible.

So all of that said, we are interested in a single primitive type for now largely because we'd like to avoid duplicating our efforts across multiple versions of each math class - we just don't have time for premature optimization. Adding support for less precise math is something that is largely an exercise in copying and search and replace.

On the subject of immutability, we've taken a rather simplistic approach that "works". Basically we're using a final boolean mutable field and hiding other member fields behind accessor methods that check for immutability. Nothing fancy, and a new better way may come as a collaborative community starts participating.

Ardor3D - An Introduction

Back about three months ago, I announced on this blog that it was time for me to move on from jMonkeyEngine (jME) and work towards bringing to life a new, more professionally driven 3D Java engine. Three months is not a lot of time to create a better engine, but together with my good friends Rikard Herlitz and Petter Måhlén, I believe we now have something special to introduce to the world: Ardor3D.

Ardor3D began life as a fork from jME's com.jme and a few of the com.jmex packages. This was done for a few reasons:
  • We felt there was a lot that was good code that could be reused.
  • People (such as clients of Ardor Labs) use jME and it would be useful for porting to be as straightforward as possible.
  • We could legally re-license the parts we had written ourselves (or wrote the majority of) to fit the Ardor3D license.
  • Parts we could not relicense, we could rewrite or even just keep on the jME BSD license.
We evolved from there rapidly, throwing out large portions of the code base and adding in some of our own. Of particular note, we tossed out (those with weak hearts may want to skip down a bit):
  • the *.app package and everything under there. So the whole concept of *Game.
  • the *.system package. So in other words, no more DisplaySystem.
  • the *.input package. jME's input system was a jumbled mess.
We also tossed out most of jmex and got rid of packages like animation, curve, entity, as well as lots of individual classes.

Ok you're saying, enough about the purge. Tell me about the new stuff.


Math:

All of the basic math objects were rewritten as double precision and include the ability to be immutable. Added is a new Vector4 class, gone are several lesser used classes like Eigen. We are also now using a new Transform object in our scenegraph classes to represent, well, the transforms. What's particularly nice about the new math classes is that it makes handling macro and micro scale scenes and cameras in such scenes a lot easier and more stable.


RenderStates:

In Ardor3D you can new up your RenderState classes whenever and whereever you like. Instead of:

DisplaySystem.getDisplaySystem().getRenderer().createTextureState();

how about:

new TextureState();

There are no implementation specific RenderStates to worry about, so the import/export process is much simpler as well and can be done in any thread without access to a Renderer or OpenGL binding.


Scenegraph and MeshData:

Instead of working with TriMesh, QuadMesh, SomeFunkyMeshICreated, etc. the scenegraph is nicely split into scenegraph classes (such as Node, Spatial and Mesh) and primitive data such as your vertices, indices, normals, etc. (encapsulated in a new MeshData class). This split makes it trivial to reuse mesh data in your scene (make two Meshes with different transforms and reuse the same meshdata object.)

MeshData stores one or more IndexModes that allow you to specify if the data inside is triangles, quads, strips, etc. I say one or more because you can also specify lengths, which are basically a way to say that given an IntBuffer for indices, the first X indices make up one draw call, the next Y make up another draw call, and so forth. Together with multiple IndexModes you can have a single Mesh that makes up a complex geometry (for example, a cylinder where the length is made up of a strip and the two end caps are triangle fans.)

Also of note, we have protected the SceneGraph objects a lot more from changes that it can not easily detect. Thus it is much more aware of changes to itself and able handle most normal updates itself. (In most cases you'll never have to remember to updateModelBounds, updateRenderStates, etc again.) Not only is this easier to use, but it has allowed us to skip a lot of excess computations during scene updates. A nice feature these changes allows for is event based notification when a scenegraph changes. You can attach a listener to your root node, for example, and use those updates events to decide to refresh the screen.


Rendering:

We flipped the concept of rendering. Instead of a monolithic Renderer that has to understand how to do the core rendering for all objects, now the logic for rendering an object lies in the object itself. The Renderer is simply a tool for you to use to get your rendering done, with available calls such as doTransforms, setupVertexData, drawElements, etc. This should allow for much wider range of custom scene objects.


Modularity, AWT and the core:

We've broken up our source to be standalone modules at the project level, keeping the core of Ardor3D nice and lean. It also has no AWT references which should make it easier to port to certain future platforms. The core supports loading TGA and DDS textures, and you can use AWT to load png, jpg, gif and bmp by making use of Ardor3D's extensions.


Canvas/Canvas Renderer and app:

With DisplaySystem gone, you still need a way to make windows and canvases. This is now accomplished in with a combination of Canvas which signifies where the GL context will be used (such as AwtCanvas, SwtCanvas, NativeCanvas) and CanvasRenderer, which is the tie to the OpenGL binding you are using to implement the rendering (Such as JoglCanvasRenderer and LwjglCanvasRenderer.) This is an area still heavily under construction, but we're happy with the results so far.

As I mentioned previously, gone are the app.*Game classes. Instead we have created a modular MVC system of Updater, View, and Scene interfaces with a Framework class that can be used to bring them together. These plug nicely into the CanvasRenderer. It may seem like a lot to pull together, but it's fairly simple and we have examples. We've also made it explicitly possible (although not necessary) to use Dependency Injection via Guice to do a lot of the setup for you.


Input:

As I mentioned, we've done away with jME's old input system. In its place is a new event based input system that nicely handles multiple rendering targets. Event trigger conditions use the Predicate interface from Google's collection package, allowing you to put together nice trigger conditions like "when the enter key is held down and I am dragging the mouse..." It's still somewhat of a work in progress and probably will change as we get new use cases. A replacement for FirstPersonHandler using this new system is already included in the core, and I've successfully used the new input package at Ardor Labs customers.


License:

Ardor3D is licensed under the zlib/libpng license. This is a permissive open source license that is also used by great game middleware such as Bullet.


Wrap up:

Our first public release is coming in a week or two and I hope this small taste has left you hungry to give Ardor3D a try. When you do, keep in mind that we are presently at release 0.2 and still have a ways to go before 1.0. Still, I think we've come a long way in three months and have some great things to show you!

Stay tuned, and Happy Holidays! :)

Ardor3D erelong

I have been asked several times recently if Ardor3D is being worked on or not and if it would ever see the light of day. I'm happy to say that the answers are yes, and yes. Ardor3D has been a part of both my and Rikard's day jobs recently and so we, along with a fellow named Petter Måhlén (another Swedish code genius), have spent quite a good amount of time on it. In fact, things are progressing well towards having a useful Ardor3D "core" ready for everyone to start poking at and playing with soon, perhaps in the next month or two. It will be very much an alpha API, subject to change, but the idea is to have a solid beginning to form a community around.

As we get closer I will write more here about some of the different paths we took with Ardor3D and introduce you to the API.

And now, back to a crazy work schedule...