The scene is basically a tree containing shapes and the actions that can be performed on them (behaviours). We have all seen the classic “HelloUniverse”example a thousand times (and if you haven’t go and look at that, including the code, and then come back here) so rather than repeat ourselves, lets create our own basic shape3d type object and put that in the universe instead.
Our new Shape is going to be a simple square, effectively a two-dimensional figure, based on 4 points. To start with lets call those points A B C and (you guessed it!) D.
There are our points, if we wanted to have a whole lot of these objects flying about we wouldn’t make the points static for the obvious reasons. Now we have our four points, enough to create a square between –0.5 and 0.5 in the X axis and 0 and 1 in the Y axis. Next up we need to tell Java 3D how to connect them. This involves placing their descriptions into three different arrays, which I’m doing in the constructor of our class. First up we create an array of co-ordinates, which can look like this:
This has given us two faces, a front and a back. If we only created it as a 4 point array and then rotated the shape you would find the surface was only visible from one side –I expect most of you have found places in 3d games where a bug let you get stuck half way into a wall and you could see straight through it- this is the same effect. Of course, if you know that no-one will ever look at it from behind then there is no point creating a back face- this can even be useful if you have a dynamic camera as it can see through walls it gets stuck behind. I’m expecting that we will see this from behind so I’m creating two faces.
Notice that the back is the same sequence of points in reverse order. This is what enables you to see the face from the other direction. When the points are joined in a clockwise direction the surface is visible to the viewer, when they are not, the surface is not- we can use this to cut holes in our face, of which more later. For now, we have two more arrays to declare:
What do these two do? First up the stripCounts tells the system how many of the points in pts belong together to form a shape- the first stripCount is the first four points of pts, forming a square, the second is the second, forming a second square from the other side. The contourCount array tells the system how many of those shapes belong to a single face of the object. This means that if we had another four points called Aa, Bb, Cc, Dd which are inside A, B, C, D we could insert those to the pts array from 4 to 7, ordered Cc, Bb, Aa, Dd, add a third stripCount value of 4 and give contourCount[0] a value of 2 and what you would end up with is the shape Cc, Bb, Aa, Dd cut as a hole through A B C D. I’m not going to go into that in any more detail, just go ahead and experiment. After all, what is the worst that could possibly happen?
So now we have our arrays of numbers we need to turn them into a Java3D shape. This is done using the GeometryInfo object. It works like this:
The first bit is fairly self explanatory but you will almost certainly find that you get problems at some point caused by the fact that the number of points, strip counts and contour counts need to add up correctly.
Next up we should look for a moment at the NormalGenerator. Normals are used to calculate how your shape gets shaded and how smooth it looks. If you want it to be possible to light your shape, you will need to generate normals on it. The setCreaseAngle method sets the angle beyond which the NormalGenerator will not smooth angles, so if you want your fairly flat shape to have every contour clearly defined set a low crease angle. For the shape we are making now the crease angle doesn’t matter, but if I explain it now I won’t need to explain it later when we do need it.
Finally we set our Geometry to the one we have just created:
And that, as the saying goes, is that.
All that is left to do now is to create our BranchGroup so that we can see our creation and make sure the camera is in a suitable position for it to be visible. These are two fairly trivial tasks that you have doubtless seen a thousand times in a thousand different tutorials, so I won’t give you more explanation than it would take for me to understand it. I hope you have all day…
The BranchGroup is the basic element of the Scenegraph and it can have as many children as you want. Children can include lights, shapes, behaviours and other Groups whose children can also be lights, shapes…you get the picture.
All we want to do is create our root BranchGroup ( named objRoot, for tradition’s sake) and add an OurShape2D to it. So lets start by doing that:
So now we have created os2, an instance of OurShape2D() we are going to pause for a moment from our “most basic”approach to add an Appearance to it. The appearance is used to describe the appearance of a shape, as you might expect. Later we will use it for texture mapping and it would also be used to control the transparency of shapes and a whole lot more besides, but for now we will just make our shape a simple colour. You will notice I have spelled that the English way. Being English makes it really confusing when you have to deal with Color objects in java. What we are doing here is creating a new appearance and then creating a material. The way we instantiate the material is using a creation clause that sets it’s ambient colour, it’s emissive colour, it’s diffuse colour and it’s specular colour with the floating point number at the end representing it’s shininess. The different types of colour have different effects which are summarized very neatly in the javadocs, so I won’t repeat them here. The ambient colour is most important, being the colour that is reflected when white light is shone on the object, in this sense it is the “basic”colour of the thing. In our case the ambient colour is 0.7 red, 0.2 green and 0.8 blue, which is purple.
Appearance app = new Appearance();Next up we will add an ambient light to the scene. Ambient light is the basic background lighting that affects everything equally. In real life there is almost always some level of ambient lighting and this is equally true of 3d games. The colour of this light is 0.4 in all channels, which is a grey colour (or dim white light, as you would probably think about it in reality.) With any light source we need to know how far it will reach as well and for this we use a BoundingSphere. This takes a point and a radius within which the light will influence things:
You will notice that bounds is not initialised as a BoundingSphere here, that is because I have created it at the class level because we will need it elsewhere.
Our final action is to add the light and the shape to the scene. We do this by adding them as children of objRoot, like this:
The compile option there allows objRoot to optimise the scene to make it perform better when displayed.
We could just uncomment the last two lines of StartHere, but there are a couple of other things we can do first, to make it easier to look at the scene. First up (after we add the BranchGraph) we get the ViewingPlatform from the SimpleUniverse and then we call it’s setNominalViewingTransform method to put the ViewPlatform (effectively our camera) in the right place to view what is happening within 1 metre of the origin:
You will be relieved to know there is nothing confusing about the fact we have both a ViewPlatform and a ViewingPlatform because their names are in no way similar.
Next up I am going to break from the “simplest”model again and add a behaviour to our ViewPlatform. A behaviour controls the movement of objects in a scene over time and how things interact together and interact with the user. The OrbitBehaviour, which we will use, is particularly handy as it allows us to use the mouse to move the ViewPlatform around the scene. This is handy for checking out shapes are the way we thought they are and that they look right from all directions.
And that really is it, when you run the applet you should get something that looks (after a few rotations) a bit like this :

Well done! We have taken our first step. I would suggest playing around with the appearance and the scene to see what happens, try adding lights and perhaps textures. After all, what is the worst that could possibly happen?
Previous: Getting Started | Back to the Index | Next: That Other Landscape