3d engine using openGL directly

Hi you all! I’m currently unsure what to do. My goal: I want to write a 3d engine. However, I am not sure which low-level API to base it on. AFAIK I have three options:

  1. Base it on Java3D. This sounded very good to me at the beginning because it is portable and the API allows a lot of optimization in the background. However, I did not read any “performance success stories” yet (only about success in development time), and the API is not exactly what I need (maybe it works with some tricks though).

  2. Base it on an OpenGL-for-Java binding (LWJGL, GL4Java, etc.). This leads to problems as well: When it comes to transferring all the data of a really complex 3d object down to OpenGL, the repeated JNI calls seem to be a performance problem (can anyone clear this issue?) But an OpenGL binding seems to be “almost good”

  3. Write an own Java/native binding which uses OpenGL at the native side but offers a higher-level interface to the Java code. This would allow to create an API which is designed specially for Java (unlike OpenGL) and also does a lot of caching on the native side.

As you probably see, I favor the third option. Note that I understand the difference in Java3D vs. OpenGL as “scene graph vs. immediate-mode access”. I would write the scene graph / management part completely in Java then (the native part would work at a lower level then scene graphs).

It also seemed to me that OpenMind is similar to what I want to do, but like Java3D its API is not what I had in mind.

My question is, does this sound like a reasonable approach?

Thanks in advance.

  1. You are right, it only seems to be a performance problem. The reality is that the JNI overhead is so small as not to be measurable. Don’t reinvent the wheel, and use our binding :slight_smile: Then your engine will be much more easily made to run on other OSs.

Cas :slight_smile:

Actually, I wanted to write a “lowest layer” (the only part of the program that contains native code), set it on top of OpenGL and provide a different interface to the Java part. However, I have noticed that I don’t get around providing some functions that are actually the same as OpenGL functions. So I could as well try an OpenGL binding :slight_smile:

One thing would be important to me though: In case I find a part of your mapping that becomes a bottleneck because it works through JNI, is it then possible to replace only that part with a self-made native library?This native library would do nothing than to run some OpenGL functions in a kind of “batch mode” to avoid JNI. I think it should work, because OpenGL is designed to work that way, but I want to be sure.

Not that I expect such problems, but I don’t want to change the binding again, should they appear.

I think I can state with absolute certainty that there will be no such bottleneck. Any bottlenecks that do exist will be from using the GL API incorrectly in the first place. It has been extremely cleverly designed to make using it over an interface as fast as possible.

The next most likely bottleneck will be in your Java code and relates to memory bandwidth and floating point performance, separately. Vote for Structs!

Cas :slight_smile:

Morin,

Out of interest, what other interface were you thinking of supplying to access your native layer? I assume its meant to be faster that JNI to avoid the bottle neck?

The other other interfaces that might let java access a native layer I can think of would be file or socket related which I would have thought would come out way slower than JNI.

Kev

Just found out that LWJGL already supports what I need! In fact, your library looks very similar to what I had in mind. Looks like the right choice to me :slight_smile:

@kevglass: I wanted to provide a higher-level API than OpenGL to the Java side, but still based on JNI. Like, transfer an array of vertex data to the native side at startup and then, at runtime, do something like “batch processing”: one JNI call to a native function which sends all data to OpenGL in a tight loop. In other words, exactly what I found buffers in LWJGL to be :slight_smile:

And about structs: I’m not sure if that really speeds things up. Because, before you can access the members of a struct you have to set up the struct itself (as a window to the buffer). Either this takes more time than you gain, or you cache the struct itself and that takes a lot of memory when you do it everywhere.

You DO gain some cleaner code, but you could get that otherwise, like:


// normalize vector at position 20
buf.readVector3f (vec, 20);
vec.normalize ();
buf.writeVector3f (vec, 20);

This is nearly as clean. To solve the speed problem, I think another trick than structs is needed. Speed is only a problem anyway when you want to perform some operation on all elements of a big buffer - The term “batch processing” comes to my mind again.

Cas already touched point 2, so I’ll take a chance at 1.

Java3d is less portable than opengl. You have opengl bindings on every platform out there which has both java and opengl. For java3d, you need both of these, plus java3d itself - which is not so easy in some cases (see Mac).

Only thing you gain is ability to choose between opengl and DirectX on Windows platform. In theory it could be a good option, if some company provides a lot better DirectX drivers than opengl ones - but is it a case today for any cards ? On downside, you will have to fight with java3d incosistencies between these two bindings.

Java3d gives you easier interface and better performance for some projects. But at the same time you pay with portability and possibilities (at least before 1.4 will come out).

[quote]Like, transfer an array of vertex data to the native side at startup and then, at runtime, do something like “batch processing”: one JNI call to a native function which sends all data to OpenGL
[/quote]
You can go one better than that - with GL display lists or various extensions you can cache vertex data on the server side (ie, video card ram) and avoid having to shuttle data across not only the Java/native boundary, but also the physical AGP bus :slight_smile:

(OT) Morin, Structs solves not only the ugly requirement that you read and write chunks of buffers in all sorts of irritating ways and have to position buffers all over the place, but it also solves the memory bandwidth issue as it allows you to operate directly on data in-situ, and with only one bounds check at that (which can be hoisted anyway if in a loop). Memory consumption of Struct instances is not an issue; you will typically only need 1 instance of a Struct to read all the elements in a StructBuffer, by virtue of its reusability.

Cas :slight_smile:

[quote] Java3d is less portable than opengl. You have opengl bindings on every platform out there which has both java and opengl. For java3d, you need both of these, plus java3d itself - which is not so easy in some cases (see Mac).
[/quote]
I disagree with that comment whole heartingly. Java does not come nativly installed on any OS maybe except for sun. As I agrued before, if you are gonna use Java in any application, you cannot expect the user to have the latest jre that you might be using. Hence you need to package this w/ your app. Programs written in C most of the time don’t have this problem; however, most retail games include the latest DirextX and OpenGL on the disk. Whats the 5 to 13 mb for j3d when your game is most likely much more then that?

[quote]Java does not come nativly installed on any OS maybe except for sun.
[/quote]
You forgot OSX. And several Linux distributions. And IBM mainframes. And HP-UX machines. And FreeBSD already has a contract to bundle the JRE.

You know, come to think of it, Windows is the real problem here…