UpgradingClientTo3D.html
09sep10 CmdrZin
07dec10

ref1: Davison, Andrew, " Killer Game Programming in Java", 2008, O'Reilly
ref2: Java 3D API (1.5.2), http://download.java.net/media/java3d/javadoc/1.5.2/index.html

    java -jar bin/sgs-boot.jar tutorial/conf/ZMUohMyNB.boot
to launch the server locally

Upgrading the Client to 3D

Since the initial test went so easy (see Notes), I've desided to revisit the Client and I think that it's architechture needs to be redone.

Here's the layout of the Client as it is right now.

Current Client Classes
Looks like the best thing to do is put it in the left area of the boxNorth. Not bad, need to resize the text area.
Need to reset the WrapCheckers3D back to 400 x 400.

And here it is.

New 3d Client

Can always widen the text area if needed, but this lools good. Now to hook up the messaging so things can appear in the 3D view and move around when Players move from room to room.
Went back to the book and worked through more chapters. Going to bring in ch18 as the starting point and remove what's not needed.
Copy ch18 files and folder to replace WrapCheckers3D files and folders..delete the old kgp_ch15 folder..replace with core3d..
Need to add NCSA library jar..
Add to Libraries portfolio.jar from KGP files.
Change MudClient.java
//import kgp_ch15.WrapCheckers3D;
import core3D.WrapTour3D;
//        WrapCheckers3D w3d = new WrapCheckers3D();
        WrapTour3D w3d = new WrapTour3D(worldSetup,this);
Add
    private String worldSetup = "ctour.txt";
trimm WrapTour3D down to 400x400...
  private static final int PWIDTH = 400;   // size of panel
  private static final int PHEIGHT = 400;
build and run..too cool..once you give focus to the panel, you can move the robot around..but need to size down..
and disable the stupid hand..Also put on the TODO list. Use mouse wheel to zoom in/out and mouse to move view.
Change WrapTour3D.java
Delete fullscreen set and use
    setPreferredSize( new Dimension(PWIDTH, PHEIGHT));
good..back to normal..going to save this state and start cutting out unneeded code then update deployed Client so people can see whats coming..
18sep10
Ok, time to trim the new 3D Client code and clean up the Client also.
Change MudClient
rename (refactored) initComponents() to buildGui()
Add comments header to buildGui()
Use Container object to hold everything instead of a JPanal (pane). So, delete
        this.add(pane);
and add
        Container c = getContentPane();
        c.setLayout( new BorderLayout() );
        ...
        c.add(pane, BorderLayout.CENTER);
to put stuff into the JFrame for display. Build and test..still works and looks the same..
Try creating pane locally in buildGUI() instead of having it as a global.
        JPanel pane = new JPanel();
This may save memory or improve object control. Still works..
Rename boxRight to panelRight since it is a JPanel and not a Box object.
Move components for Player Stats and Info from MudClient.java to ClientInfo.java.
Lots of stuff moved over..all seems to still work..
Rename box1 as boxCenter and box2 as boxSouth for better naming. Seems to load faster now.
19sep10
More trimming. Removed all models except coolrobo files. Edit ctour.txt to remove references.
Using Obsticales.java as a basis, designing a Rooms.java class. For right now, it will construct a Room as a 3D object rather than load a model. We'll see how it goes.
Make a new Class Rooms3D.java under core3d.
All rooms will be added as a group and then made visible when they are explored.
Add some initial varibles for object definitions and there code packages (see code)
Add a constructor.
    public Rooms3D()
OK, here's were we diverge. Going to make a sub-class call Room and store them in a List in Rooms3D. Things in Room will position, color, visible flag, etc.
(see code) 4 little red boxes on the floor..too cool..
20sep10
Using the Obstacles.java file as a guide, I descided to go with Box objects for rooms.
I made a Rooms3D.java with a Room subclass. Rooms3D uses a Map HashMap to store <String, Room> for lookup. The Rooms3D class has a makeRooms() method that add the TG of the rooms to a Group. The rooms don't really do anything, so the Group seemed the easiest way to display them. I'm hoping that I can add and delete from the Group.
The Room class holds the dimensions and locations plus a visible flag. It may get expanded later.
24sep10
Updated the MudMain.properties file to include position and dimensions for each Room. Not exact, but good for placeholders.
02oct10 rev 208 baseline
Back on the Client. Before adding the Room position and dimensions parser to the decription text, I thought I might fix the view controls first. The current view follows the robot, sort of, and can zoom in (i) and out (o). The earlier code[1] used the OrbitBehavior method that would use the mouse. For this game, it's the preferred way to go.
Change WrapTour3D.java
Add orbitControls() from WrapCheckers3D.java[1]
Remove .addKeyListener() for closing the window.
Add
    orbitControls(canvas3D);   // controls for moving the viewpoint
build and test..woo hoo..camera and robo view both work..copy changed files to ZMUohMyClient
    MudClient.java
    WrapTour3D.java
    Rooms3D.java (some initial code for parsing)
clean and commit server code..rev 209..ok, back to the parser...
the Room info is appended to the Room description as ..@(x,y,z)@(L,W,H), so a bit of token matching is needed. The text is in a StringBuffer object.
Used .indexOf() and .substring() to extract output three numbers with comma separators.
Then trimmed the output String by removing the Room stuff using .substring(). (see code)
Ok, we have two strings now with the 3 floats to convert to Vector3f objects.
SideTrack: Did a little more research on getProperties() for retrieving file paths in jar arcives.
Change PropManager.java
  // TODO: Try this to get path
  String mPath = getClass().getResource("/core3d/models/").toString();
  System.out.println(mPath);
  s = modelLoader.load(mPath+fnm);   // handles many types of file
//   s = modelLoader.load(pathModels+fnm);   // handles many types of file
Change WrapTour3D.java, use lower case to match filename EXACTLY...
was
    bob = new TourSprite("Coolrobo.3ds", obs);   // sprite
is
    bob = new TourSprite("coolrobo.3ds", obs);   // sprite
No compination of cod works. The correct path can be optained, but the model loader can't find a file
that's in a jar archive..oh well, just have to zip jar, lib, and model folders to gether. No more WebStart.
Back to the Client.
Hmm..need to change rooms Map to use Vector3f of the room as the key. This can be recovered each time a description message is sent. The same info can tacked onto movement messages (a new message type) to update rooms.
Make WrapTour3D object wd global so that MudClient methods can access its methods.
Overload addRoom() method to call each time a Room description is received.
Procedure
    Check rooms list
        If on list, ignore, else build new Room and add to list.
    Move Player's avatar into Room (new code to be done later)
Almost works..need to add new items as a BranchGroup..hmm..WOO HOO, rooms pop up as you move!!!
clean and commit..rev 210
04oct10
More playing around with the Room boxes. Added this code to display them as outlines instead of solid Red.
Change Rooms3D.java::makeRoomObj() (from Ch 16, pg 438)[1]
  Appearance obsApp = new Appearance();
  // create obstacle node
  if(false) {
    Material mat = new Material(black, black, red, specular, 100.f);
    mat.setLightingEnable(true);
    obsApp.setMaterial(mat);
  } else {
    PolygonAttributes pa = new PolygonAttributes();
    pa.setCullFace(PolygonAttributes.CULL_NONE);
    pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
    obsApp.setPolygonAttributes(pa);
  }
  Box obs = new Box(dimensions.x, dimensions.y, dimensions.z,
                Box.GENERATE_NORMALS, obsApp);
I can make the if() conditional later if needed.
Now I need to fix the properties file so the rooms have the correct parameters.
Ooops..added on last thing..initUserPosition() to set the view at the begining.
25nov10
After having added a PositionMessage that is broadcast to all Clients anytime something enters a Room, it's time to add the avitars to the 3D display so that the User can watch things moving around.
The Client will use a Green dot for the User, Blue dots for other Players, and Red dots for everything else. The dot is placed in the center of the Room that it enters and given a slight random offset in position so that multipel dots do not sit on top of each other.
Each PositionMessage provide an ID, an object type, and the 3D position vector. The Client maintains a List of avatars that it has received messages about. When a new PositionMessage is received, the object is either added or it's position updated.
NOTE: A Player leaving the game message has to be serviced also. TODO later.
Each avatar is based on the Sprite3D class and will be added to the global scene (sceneBG) with
   sceneBG.addChild(<avatar reference>.getAvatarBG()).
The avatar will use the TransformGroup (TG) concept[1] to allow it to be moved around.
So, first thing to use the Sprite3D class, that should be in the remote Client project, to make an Avatar class. The TourSprite or AlienSprite classes can be used as templates. Just use the Copy then Paste->Refactor Copy selections activated by the RMC.
Since the avatars move point to point instead of left right etc., add a moveTo( point ) method to replace all of the others. The moveTo() will have to calculate the correct x,z to pass to moveBy(). The y axis movement will be added later.
04dec10
Ok, back to the display. Adding another Sprite3D constructor that does not need a model file name or a collision object list. Passing a Node object to the constructor maintains the Sprite3D purpose of moveing around whatever the sprite represents. So the building of an sprite, whether a geometrical object or 3ds model, is handled at a higher level.
Rats..can't pass in the object with super() because super() has to be the first call in the constructor and the object has not been built yet..try adding a method to Sprite3D to do that,  addSpriteObj() and call it after building the sprite model or geometric shape.
NOTE: I should be using the lighter weight Point3D to store position data.
Adding comments to code where the PositionMessage is received in Client.java.
  // Check it this is a new Avatar. Add or Update as needed.
  // Map<Integer> has list of Avatar IDs
  // If hasID(msg.getObjectId())
  //  update(ID,position)
  // else
  //  add new Avatar
Will get back to this after getting the display to show something when the message arrives.
Sidetrack, added methods to get Id, Type, and Position to Avatar class.
Set Avatar.makeDot to use material colors for Appearance..
Hmm..since adding a new object, a BranchGroup is needed??..
pg390 "BranchGroup allows children to be added or removed from the graph at runtie".
Hmm...per the  Java 3D API 1.5.2, Only a BranchGroup can be added as a child to a compiled Group (SceneGroup)..try making a BranchGroup for a new Avatar..
Java Tutorial: Might be able to set sceneBG.ALLOW_CHILD_EXTEND to let add after being compiled..
    // Try this to allow adds after compile.
    sceneBG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
Nope..still errors..try BG method in WrapTour3D.java..
  public void addAvatar( Avatar av ) {
      BranchGroup newBG = new BranchGroup();
      newBG.addChild(av.getTG());
      sceneBG.addChild(newBG);
  }
BINGO!!!.. Da Box
Avatar Box
Need to change the size to 0.1 and use the room coordinates for placement. Add
        setPosition(avatarPosition.getX(), avatarPosition.getZ());
after adding sprite. Oops..forgot to convert to map coordinates..doh..and we have dots in the boxes..woo hoo..
Commit..rev 226
Updating Client Project files:
    client/MudClient.java
    core/Door.java
    core/MudUser.java
    messages/MessageFactory.java
    messages/PositionMessage.java
    messages/Message.java
    core3D/Sprite.java
    core3D/Avatar.java
    core3D/WrapTour3D.java
    core3D/TourSprite.java
    core3D/AlienSprite.java
    core3D/Rooms3D.java
build Client..works..need to build Linux version also..
ok..back to making it better
Adding comments to code where the PositionMessage is received in Client.java.
  // Check it this is a new Avatar. Add or Update as needed.
  // Map<Integer> has list of Avatar IDs
  // If hasID(msg.getObjectId())
  //  update(ID,position)
  // else
  //  add new Avatar
Changes MudClient..first thing is to set up a service for each type of Avatar. This will make it easyer to add features later.
Add a switch/case statement to call serviceUser, servicPlayers, serviceMobs. (see code)
Add PLAYER to enum list. MOB are treated as ITEMs for now..will look into this later.
Here's the code for the User. The others are similar.
    private void serviceUser(PositionMessage msg) {
        Integer id = msg.getObjectId();
        if(avatarList.containsKey(id)) {
            // update positon
            avatarList.get(id).moveTo(msg.getObjectPosition());
        } else {
            //  Make a new Avatar
            Avatar avatar = new Avatar(msg.getObjectId(),
                    msg.getObjectType(),
                    msg.getObjectPosition());
            // add to list
            avatarList.put(id, avatar);
            // add to display
            w3d.addAvatar(avatar);
        }
    }
build and see what happens..and it WORKS....but need to check the move to value calcs..
Fixd that (I think)..back to the game play now that you can see yourself walk around.