Scene Graph

When you use different classes for them you have additional code to maintain…

Making a difference between points and vectors by using different classes is actually new to me. I know two solutions, both make no difference at all, both call the thing (which is essentially a 3-tuple) a vector, and none of them produces any ‘dirty’ code if you know what you are doing.

Solution no. 1 (which I’m using in my engine): There is very very very seldom a case where you do not know if a vector means a position or a direction. Actually I have not yet seen any such case. There are simply two transformation functions, one for points and one for methods.

Solution no. 2 (which OpenGL uses): Very nice, but requires additional CPU time. All vectors are stored as 4-tuples, where the fourth value is 1 for positions and 0 for directions. A transformation is stored as a 4x4 matrix where the rightmost column contains the translation part of the transform. Advantage: You can store the translation in the matrix as well. Also, computing the signed distance of a point to a plane means simply computing the dot product of two 4-tuples.

BTW the ugly code when transforming normals may have another reason: You cannot transform normals the same way as you transform vertices. This only works for either orthogonal or orthonormal transformations (not sure). Otherwise the normals are tilted towards the surface during transformation.

Sure sure - homogenious coordinates are very common in 3D - not only in OpenGL - and vecmath and Java3D deeply rely on them.

Anyway there is a difference between a technically driven design (a vector is a 4tuple, a point is 4tuple) and a semantical design (a vector is a direction, a point is a position).

If you refuse to distinguish vector and point, there consequently shouldn’t be a Color class (Color is a 4tuple). And in some cases, it might even make sense to treat colors like points.

It’s a matter of taste in the end. I think vecmath is correct and OK for me, but I could live with other solutions as well.

BTW, even vecmath isn’t completely consequent by keeping these things apart.

A quick update:

The scene graph now has everything (I think) except:

Bounding objects
Sound based objects (I’m leaving these out for now)
Behaviors

This weekend I hope to get each of the geometry objects functioning with all of the different Appearance component objects when rendering.

I realize this is a lot to ask but since I’m such a newbie to this stuff I was wondering if some folks would be willing to help me write little test programs to make sure everything is working correctly. After I have a testable version of course. The problem is I can infer certain thing but I have no way of knowing if the render results I get are actually what should happen.

No takers huh?

Oh well, how about anyone that would be willing to fill in the code for the Transform3D, BoundingSphere, BoundingPolytope and BoundingBox class methods.

For the Bounding classes the intersects and combine type methods.

The Transform3D class is a boat load of matrix calculations.

One other question, I usually just make what I write free-ware and let people get it from my web site however I think this should be a SourceForge project and under the same open source license as the LWJGL. When there are two projects that are related what is the best way to make sure the package names don’t conflict?

Same way you’ve always done it - put them in your own domain package (com.scottshaver.*)

Cas :slight_smile:

Another small update, if anyone cares…

The following classes are implemented in the com.sas.lwjgl.scenegraph package.

AmbientLight.class, Appearance.class, Background.class, BoundingBox.class, BoundingLeaf.class, BoundingPolytope.class, BoundingSphere.class, Bounds.class, BranchGroup.class, Clip.class, Color3f.class, Color4f.class, ColoringAttributes.class, DecalGroup.class, DirectionalLight.class, ExponentialFog.class, Fog.class, Geometry.class, GeometryArray.class, GeometryStripArray.class, Group.class, ImageComponent.class, ImageComponent2D.class, ImageComponent3D.class, Leaf.class, Light.class, LinearFog.class, LineArray.class, LineAttributes.class, LineStripArray.class, Locale.class, Material.class, Node.class, NodeComponent.class, OrderedGroup.class, PointArray.class, PointAttributes.class, PointLight.class, PolygonAttributes.class, QuadArray.class, RenderingAttributes.class, SceneGraphException.class, SceneGraphObject.class, SceneGraphRuntimeException.class, Shape3D.class, SpotLight.class, Switch.class, TexCoordGeneration.class, Texture.class, Texture2D.class, Texture3D.class, TextureAttributes.class, Transform3D.clas, TransformGroup.class, TransparencyAttributes.class, TriangleArray.class, TriangleFanArray.class, TriangleStripArray.class

The rendering engines will go in the com.sas.lwjgl.render package and currently only has one class: SimpleRenderingEngine.class

The package com.sas.lwjgl.examples contains example programs. Mainly I’m unsing this to test things with.

The package com.sas.lwjgl.imaging contains classes that can read different image file formats (no dependence on anything coming from Sun except the basic language constructs of course). These must implement the ImageFile interface and there are currently two. TargaFile.class and WindowsBitmapFile.class

Where it stands right now:

I keep thinking I’m ready to deal with the Appearance attribute rendering and then I find something else I’ve forgotten to create. I think that is almost over. I have a few things to finish up for the Transform3D and Bounds classes, then I need to create the View and ViewPlatform replacement classes and I can focus on the rendering engine. Just remembered I have to go through all of the classes and put in the cloning methods, but this can wait.

Wow, this is a very impressive list!

Do you re-implement Java3Ds principles or do you have something very different?

[quote]Do you re-implement Java3Ds principles or do you have something very different?
[/quote]
I think you’re asking if I’m following their design Ideology, if so then the answer is, yes as closely as possible. Here is my current readme.txt file perhaps it will shed some light.


/*------------------------------------------------------------------------
The LWJGL (Light Weight Java Gaming Library) is an open source project to
provide a direct binding to OpenGL for the Java(tm) language. LWJGL is only
intended to provide that low level binding and as such lacks certain tools
that many programmers need to complete their projects.

The LWJGL Scene Graph (LWJGL-SG) is a separate project intended to give 
programmers some of those tools. The major focus of the LWJGL-SG is to 
provide a scene graph for 3D programs that use the LWJGL. Other utilities
may be included in the library though (such as the imaging package for
loading image files).

This scene graph is based heavily, class architecture wise, on the scene 
graph provided in the Java3D API. In fact the initial version of this 
scene graph was constructed after reading the book: 

The Java 3D API Specification (ISBN 0-201-32576-4)

several times, *sigh*. The book hadn't seen the light of day since I 
bought it a long long time ago. By the time I get a first release made
it will probably be totally destroyed. (Note: Because the book is old
many features of the current Java3D API my not be (and probably are not)
present in this library. That's why we have new releases.)

This is an important point, no source code was copied from the Java3D 
libraries. In fact the source code was never even looked at (I'm not 
sure if it is even available). I chose to base my code on the Java3D 
API specification for two reasons. 

First, prior to writing this I had basically no experience with 3D 
programming. I knew that there was no way I could produce something usable
without having a road map laid out for me. The API specification was my 
road map.

Second, I wanted to give Java3D programmers that were considering moving
to the LWJGL the easiest path for the migration I could. Obviously this
scene graph is not going to be an exact copy of the Java3D scene graph.
That was never the intention, but it is similar enough that porting a 
Java3D program to it should not be tramatic.

This file is an attempt to describe the areas where this scene graph and
the Java3D scene graph differ.

Scott Shaver (zparticle)
------------------------------------------------------------------------*/

**************************************************************************
Class Differences: 

This section is an overview of the main design difference between the 
Java3D scene graph classes and the classes in this library.
**************************************************************************

1> Many of the Java3D classes give the programmer to sets of methods for 
performing a task, one set that uses object and one set that uses Java
primitive types (usually in arrays). This library has left out the methods
that use Java primitives.

2> Many of the class methods in Java3D get values from the classes by 
passing in an array of primitives or objects in the argument list. I 
assume the reasoning behind this was so the API programmers could control
when references to the actual values were returned and when copies of the
values were returned. I have choosen to use getter methods that return the
actuall value references. There are two reasons for this. 

First, I don't like the other method, java should have constants built 
into the language symantics. Second, memory consumption. This library is
intended to be used for games where constant object allocation/garbage 
collection is a major no-no.

The implication of this is the following, the programmer is expected to
play nice and not modify the values in the references returned from the 
methods. If he doesn't follow this rule then he will be spending an
enormous amount of time debugging his code. :)

3> No AWT or Swing. It is important to make sure that no AWT or Swing code
creeps into this library. This library needs to following the lines of 
LWJGL and avoid using anything that makes it dependant on AWT or Swing.
Part of the reason for this is the use of compilers that can compile Java
programs into native excutables often don't have the ability to use AWT
and Swing. Another reason for this is simply that it is not neccessary and
therefore why do it.

**************************************************************************
Classes Left Out: 

This section lists the classes from the Java3D scene graph that have
been left out for one reason or another.
**************************************************************************

DepthComponent
DepthComponentFloat
DepthComponentInt
DepthComponentNative

All of the audio classes.
All of the Behavior classes.
All of the Pick classes.
The SharedGroup class and Link class.

**************************************************************************
Class Changes: 

This section lists the classes from the Java3D scene graph with the same 
names in this library that have some fundamental differences.
**************************************************************************


**************************************************************************
Things To Do:

This section lists the things that are not done but should be at some 
point.
**************************************************************************

The capability bits for the graph node objects haven't been implemented.
The constants and the code in the getter/setter methods need to be added.
When we do this the methods should throw a SceneGraphRuntimeException if
the capability isn't turned on.

----These classes need some of the methods filled in----
Bounds.java
BoundingBox.java
BoundingPolytope.java
BoundingSphere.java
Transform3D.java

The view platform, nothing is done.

Fog - needs the scope methods added
Light - needs the scope methods added

NodeComponent - uncomment the duplicateNodeComponent and cloneComponent methods
Node - uncomment the duplicateNode and cloneNode methods
Implement the cloning methods in the rest of the Nodes and NodeComponents


Okay I’m getting geared up to handle the Appearance properties of Shape3D objects in the renderer. I bought an OpenGL reference and have been matching up the gl functions with the properties so I can get an idea of what I have to do while rendering.

Since gl is a big state machine and since the state is going to have to change quite a bit while rendering the scene graph I was wondering what the correct way to save the state of gl is. For instance if I’m traversing the graph and come to a BranchGroup that contains 2 subgraphs I need to push the current state onto a stack and then traverse one of the subgraphs. When that subgraph is finished I need to pop the state off of the stack and then go traverse the other subgraph.

What functions, if any, should I use from OGL to accomplish this? If there are functions for this purpose is there a limit to how deep the stack can get?

[quote]What functions, if any, should I use from OGL to accomplish this? If there are functions for this purpose is there a limit to how deep the stack can get?
[/quote]
Use PushMatrix and PopMatrix to save the current matrix - usually the viewing or modelling matrix.

Use PushAttrib and PopAttrib with a specific flag to save information like lighting settings, line drawing modes, viewport settings etc. Can also push/pop ALL_ATTRIB_BITS for the shotgun approach!

These stacks do have a maximum depth though, and you’ll have an error thrown if you exceed it. Get the current settings with a GetIntegerv of MAX_MODELVIEW_STACK_DEPTH, MAX_PROJECTION_STACK_DEPTH or MAX_ATTRIB_STACK_DEPTH. Specifically, the modelview should have a minimum stack depth of 32, projection is at least 2, and attribute is at least 16.

With those limits in mind, you might want to consider restoring state manually, although I expect you’ll have a performance hit with that. Check the limits of current OpenGL implementations and see if it’s going to be enough for you.

Thanks a lot, that helps very much.

Things are coming along very nicely. I might have a first alpha available by Friday.

Is having GL.ALPHA_TEST enabled with an alphaFunc of GL.ALWAYS the same thing as having GL.ALPHA_TEST disabled?

[quote]Is having GL.ALPHA_TEST enabled with an alphaFunc of GL.ALWAYS the same thing as having GL.ALPHA_TEST disabled
[/quote]
Yep, sounds about right! ;D

In case you’re interested, Redbook says the default settings are effectively:

gl.alphaTest(GL.ALWAYS, 0) ;
gl.disable(GL.ALPHA_TEST) ;

Okay some stupid little screen shots of this thing in action.

http://www.scottshaver2000.com/temp/shot1.bmp
http://www.scottshaver2000.com/temp/shot2.bmp
http://www.scottshaver2000.com/temp/shot3.bmp
http://www.scottshaver2000.com/temp/shot4.bmp

These show different combinations of Appearance NodeComponent properties being turned on/off. The last one is basically the first one with a marble texture.

There are 13 cubes.

Okay I started adding the code for handling compiled branch graphs using display lists. Two questions:

1> Is there anyway to know that a card is going to have issues with display lists and therefore automatically disregard the programmers decision to use them?

2> On my GeForce 4ti 4600 When I use display lists my processor usage goes up slightly when compared with not using them. Is this what should be happening or am I doing something wrong?

Another unrelated question: Should I plan for automatically using the advanced features (OGL extensions) of different video cards? For instance NVIDIAs pixel shader extensions if they were applicable in certain situations.

[edit] http://www.reactorcritical.com/review-geforceshaders/review-geforceshaders.shtml This is a pretty good article about the NVIDIA pixel shaders in OGL.

2> On my GeForce 4ti 4600 When I use display lists my processor usage goes up slightly when compared with not using them. Is this what should be happening or am I doing something wrong?

strange, sound wrong for me

Yeah, with display lists the hardware will be pulling data from internal storage but the processor should be doing less.

Could the processor be working harder because it’s not having to wait on the hardware any more, and getting more done? ???

I’m having some difficulty getting my head wrapped around the lighting for the scene graph. There doesn’t appear to be any limit to the number of lights used in the Java3D scene graph but OGL does have a limit.

The lights in J3D have a InfluencingBounds object in them that tells J3D to only light objects with a particular light if the objects are inside of the bounds of the light. How would one go about implementing this with OGL?

In OGL it seems that an ambient light source has to be tied directly to a specific GL_LIGHTi instance. This being the case what exactly is the purpose of the glLightModel function? Can someone either point me to a dummies guide for OGL lighting or explain how the GL_LIGHTi and glLightModel function together? I simply don’t get it.

Thanks in advance.

GL is 8 lights minimum, per primative. So if you’ve got active bounds setup for each you can find the influential lights for each object/poly group, and set those as your GL lights. All fine until you get >8 per object, at which point I guess you’ll be either choosing the 8 most influential (based on brightness/type/location) or doing some sort of multipass to add them all together.

Just to complicate things, some graphics cards support more than 8 lights (GeForce cards I think are at least 16), and some cards while supporting 8, get drastic speed drops if going over (say) 4 - dropping back to software T&L I guess. So you’ll probably want to make the actual number of GL lights settable though code.

One thing that I heard mentioned a while ago was LOD’ing lights - numerous small lights being clumped together into one larger light at a distance. For example, a table with lots of candles on could probably get ~16 lights close to, but reduced to 2 or 3 lights at a distance.

The glLightModel is to do with how the specular lighting is calculated. Unless you’re doing a parallel projection, then it’ll almost certainly be better off set to a local eye (isn’t there something like this in J3D? Local eye vs. infinate eye, if i remember correctly).

Hope that helps

Okay, so it looks like I need to turn lighting on/off per object rendered based on if the object is inside of the InfluencingBounds of the light.

Seems like that would have really strange effects on the rendered scene as every object isn’t going to be effected by every light. However the material for the object has the same effect I guess given that if it is null the lighting is disabled for that object.