Now we are walking, but as you have probably noticed, as soon as we get to the bumpy areas at the side of the world we start sinking into them- we are not walking up or down the hills, we are just ploughing through them as though they weren’t there at all. Which is, if you think about it, fair enough because we haven’t done anything to change the vertical position of the purple dude, we have just set up controls that allow him to move around on the flat. So next up we need to make him handle the ups and downs of the world.
The way we do this will be to use the picking capabilities of Java3D. These are based on the creation of a PickTool that enables us to create a picking shape. There are various shapes available to us, all extending javax.media.j3d.PickShape and each one offering a different shape that we can create and that will tell us what objects in the world intersect with it. For this task we will use a PickRay, which creates a straight line from a given point in a given direction. We can create this from the centre of our character straight down and then move him up or down according to where the ground is. This will require a few changes to the behaviour and the calling code –the PickRay will have to be created outside the behaviour and passed to it and we will have to set pickability so that the landscape can be picked but the character can’t.
So looking at ClimbMorph you will notice that only a couple of places have changed. First up we now have a private PickTool picker; declared and handed to the Behaviour when it is created. We also have a whole lot of changes to the moveStep method, which we will look at now:
So, first we have incremented upSum as before, then we have created a new point3d then transformed it to match our starting point but be 2 metres above it. This point will be the starting point for our picking ray, which will point straight down so that if the ground is anything less than 2 metres above our current position we will locate it.
We also create a Vector3d called “down”- I have said this before and I’ll say it again –3D graphics has a really strong element of performance tuning about it- a Vector3d that will never do anything but point down should never be created every frame- it should be a static class level variable. The only reason it is happening this way here is that I want to have as many code changes as possible in one place as it’s easier to see what is going on. You could probably go through most of the classes here as an exercise and see how you could make them more efficient.
The PickRay has a starting point and a direction, both of which we just defined.
Now we have used pickClosest to find the first intersection the PickRay finds and return it’s PickIntersection object. We then get it’s point co-ordinates and load them into our point.
if
(nextpoint != null) So if our point
has been created properly we create a double to contain the
position of our starting point ( we subtract 2 because we
started 2 metres off the ground ) and make sure that the
point we have just picked is not the same as the previous
y position –no point doing all this work if it is. Assuming it is different,
we create a new Vector3d, copy the translation from OurTrans
into it, set it’s y value to be the new one we have
just picked and loaded it back into ourTrans. Finally we add the
step to tempTrans. After this last bracket the method is
exactly the same as the previous version. That’s all
there is to the Behaviour but we need to change a few things
in the calling method to make it work properly: Here we have created
the land as before then created the PickTool and informed
it that it is allowed to read everything about the land object.
We create our ClimbMorph behaviour handing it the picktool
as well. When we have added it to the dudeGroup we set the
pickability of that node to false –if we don’t
do that the pickray will run into our character rather than
the ground which typically results in the character shooting
vertically up in the air when you ask it to go forwards.
Not, strictly speaking, the desired effect, but one of the
funnier errors to see in action… The other major
change is that we have added a background group to our world.
This doesn’t interact with the scene at all, it just
sits there looking better than a plain black space. As you can probably
tell, this is just creating a new BranchGroup and appearance
and populating it with a sphere that displays it’s
appearance inwards. Finally we have
created a Background node, applied the Geometry we just created
and added it to the root of the world tree. So now, we should
have something that looks a bit like this: Previous: Now We're Getting Somewhere | Back
to the Index | Next: Finally
in Followcam Footage
{
double
pickY = (pickStart.y);
pickY
= pickY-2.0;
if
(nextpoint.y != pickY)
{
Vector3d
translate = new Vector3d();
ourTrans.get(translate);
translate.y=nextpoint.y;
ourTrans.setTranslation(translate);
}
}
tempTrans.setTranslation(new
Vector3d(0.0d, 0.0d, stepper));
}
PickTool
p = new PickTool(objRoot);
p.setCapabilities(s,
PickTool.INTERSECT_FULL);
ClimbMorph
mBeh = new ClimbMorph(morphAlpha, ourMorph, dudeGroup,
p);
mBeh.setSchedulingBounds(bounds);
dudeGroup.addChild(mBeh);
dudeGroup.setPickable(false);
Appearance
App = new Appearance();
try
{
Texture
tex = new TextureLoader(new java.net.URL(filePath+"skysec.jpg"),
this).getTexture();
App.setTexture(tex);
}
catch
(Exception e)
{
e.printStackTrace();
}
Sphere
outerWorld = new Sphere( 1.0f, Primitive.GENERATE_TEXTURE_COORDS
| Primitive.GENERATE_NORMALS_INWARD, App);
bgGeometry.addChild(outerWorld);
bg.setApplicationBounds(bounds);
bg.setGeometry(bgGeometry);
objRoot.addChild(bg);
