java.net: Wiki

The Source for Java Technology Collaboration


 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (7 - 22 Aug 2008 - Main.uwekamper)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 260 to 260
 mouse input. Using it, you'll also learn how to synchronize the state of your cell among many clients.
Deleted:
<
<
Part 4 - Handle input events for your cell
 \ No newline at end of file
Added:
>
>
Part 4 - Handle input events for your cell
Part 5 - Complete the cell
 \ No newline at end of file

 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (6 - 03 Jul 2008 - Main.jslott)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 256 to 256
 

Next Steps

Changed:
<
<
In the next and final tutorial in this series, you will learn how your cell can capture keyboard and
>
>
In the next tutorial in this series, you will learn how your cell can capture keyboard and
 mouse input. Using it, you'll also learn how to synchronize the state of your cell among many clients.
Deleted:
<
<
ProjectWonderlandNewCellPart4
 \ No newline at end of file
Added:
>
>
Part 4 - Handle input events for your cell
 \ No newline at end of file

 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (5 - 03 Jul 2008 - Main.jslott)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 121 to 121
  public ShapeCellSetup? getSetupData() { ShapeCellSetup? setup = new ShapeCellSetup?(); setup.setShapeType(this.shapeType);
Changed:
<
<
setup.setBaseURL(WonderlandConfig?.getBaseURL());
>
>
setup.setBaseURL(WonderlandConfig?.getBaseURL() + "/textures");
  setup.setTexturePath(this.texturePath); return setup; }

 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (4 - 02 Jul 2008 - Main.jslott)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 259 to 259
 In the next and final tutorial in this series, you will learn how your cell can capture keyboard and mouse input. Using it, you'll also learn how to synchronize the state of your cell among many clients.
Added:
>
>
ProjectWonderlandNewCellPart4
 \ No newline at end of file

 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (3 - 18 Jun 2008 - Main.jslott)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 189 to 189
 inserts the "textures/" part). This method returns an object of type ImageComponent2DURL; it's a subclass of Java 3D's ImageComopnent2D class, that is used to represent textures, among other things. Using this method to load the texture also automatically updates the window in Wonderland
Changed:
<
<
that pops up and displays the status of assets that are being download.
>
>
that pops up and displays the status of assets that are being download. The loading itself takes place asynchronously--although the method returns quickly, the shape remains texture-less until it has finished loading, at which time the texture will automatically appear. (In our case here, with a suitably quick-enough internet connection, it may appear that the shape is textured instantaneously).
 
        ImageComponent2DURL ic = AssetManager.getAssetManager().createImageComponent2DURL(baseURL, texturePath);
Line: 210 to 213
 Note: It may be required that the width and height of your image be a power of 2. (Our texture, MountainPicture.png has dimensions that are powers of 2). Please refer to the Java 3D API Documentation (specifically,
Changed:
<
<
the Texture2D for more details).
>
>
the Texture2D for more details). The second argument to the constructor of the Texture2D class takes the format that matches the texture image--in our case, RGBA (RGB with an alpha blending component). Another common format is RGB.
 Finally, you will need to modify how you instantiate your Sphere and Box objects. You simply use a different constructor for each that now takes the Appearance object you just created. The remainder of your setup() method should
Line: 231 to 235
  }
Added:
>
>
In the constructor of the Box and Sphere classes, we ask the class to generate the texture coordinates. If you are creating your own geometry (e.g. using GeomtetryArray), you will need to generate the texture coordinates yourself. Once again, a detailed discussion of Java 3D is beyond the scope of this tutorial.
 

Running With Your New Textured Shape

To recompile and re-run both the Wonderland server and client, in two separate terminal windows:


 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (2 - 18 Jun 2008 - Main.jslott)
Line: 1 to 1
 
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->
Line: 30 to 30
 

Artwork Repositories

All artwork in Project Wonderland--whether they be geometric models that were created using a 3rd party modeling tool such

Changed:
<
<
as Maya Blender or textures creating using a standard graphics drawing package--are downloaded by the Wonderland client
>
>
as Maya or Blender or textures created using a standard graphics drawing package--are downloaded by the Wonderland client
 from a central artwork repository. The artwork that comes with the Project Wonderland demo world is available via a public art server at: http://192.18.37.42/trunk/lg3d-wonderland-art/compiled_models/. Go ahead and point your web browser to this URL, you should see directories containing the models and textures.
Line: 41 to 41
 

High-Level Design

Changed:
<
<
You will enhance the custom shape cell to texture the sphere or box with an image from an artwork repository. This relative
>
>
You will enhance the custom shape cell to texture the sphere or box with an image from an artwork repository. The relative
 path (within the repository) of the texture will be specified in the cell's XML file within WFS. The path of the texture is then communicated to the client-side cell class that loads the image using the asset management facilities provided by Project Wonderland and then sets the shape's texture.
Line: 79 to 79
 

The baseURL parameter gives the URL of the artwork repository. You do not set this within WFS, rather your server-side

Changed:
<
<
cell class (ShapeCellGLO) sets this parameter based upon Wonderland configuration files. The texturePath property gives the relative path of the texture file within the artwork repository.
>
>
cell class (ShapeCellGLO) sets this parameter based upon Wonderland configuration files. The texturePath property gives the relative path of the texture file within the artwork repository, and is set within your WFS cell file.
 
Changed:
<
<

Specifying the Texture Path in *shape-wlc.xml*

>
>

Specifying the Texture Path in shape-wlc.xml

 While we are on the subject of configuration, now's a good time to add the path of the texture to your shape-wlc.xml file in your WFS. Within the cellSetup property, beneath the entry for shapeType, add the following lines:
Line: 93 to 93
 
Changed:
<
<
Note that this relative path excludes the textures directory parent--when you load this texture file via Wonderland's asset manager, it automatically prepends textures before the value of the texturePath property.
>
>
Note that this relative path excludes the textures/ directory parent--when you load this texture file via Wonderland's asset manager, it automatically prepends textures/ before the value of the texturePath property.
 

Modify the ShapeCellGLO Class

Changed:
<
<
Changes to the server-side ShapeCellGLO class are relatively simple: you just need to store the texturePath property is
>
>
Changes to the server-side ShapeCellGLO class are relatively simple: you just need to store the texturePath property in
 a member variable and populate the ShapeCellSetup class when needed. First, add a member variable near the top of the class to store the texture path:
Line: 106 to 106
  private String texturePath = null;
Changed:
<
<
Next, when you create a new !ShapeCellSetup class in the getSetupData() method, set the value of the texture path property from this class. You will also need to set the value of the baseURL property in the !ShapeCellSetup class. The value of this property is obtained from via the WonderlandConfig.getBaseURL() method. This method returns the value of the
>
>
Next, when you create a new ShapeCellSetup class in the getSetupData() method, set the value of the texture path property from this class. You will also need to set the value of the baseURL property in the ShapeCellSetup class. The value of this property is obtained from the WonderlandConfig.getBaseURL() method. This method returns the value of the
 wonderland.art.url.base property (if using a remote artwork repository) or the wonderland.art.url.local property (if using an
Changed:
<
<
artwork repository stored locally on disk). (Strictly speaking, the CellGLO superclass contains a protected member variable called baseUrl with this value, however, this tutorial code calls WonderlandConfig.getBaseURL() directly to highlight where the value actually comes from).
>
>
artwork repository stored locally on disk) defined in Wonderland's configuration files. (Strictly speaking, the CellGLO superclass contains a protected member variable called baseUrl with this value, however, this tutorial code calls WonderlandConfig.getBaseURL() directly to highlight where the value actually comes from).
 Your getSetupData() method should now look like this:
Line: 127 to 127
  }
Changed:
<
<
Finally, for the !ShapeCellGLO class, you need to modify the setupCell() method to fetch the value of the texturePath property
>
>
You likely also need to add this import statement to the top of your ShapeCellGLO.java file:

import org.jdesktop.lg3d.wonderland.config.common.WonderlandConfig;

Finally, for the ShapeCellGLO class, you need to modify the setupCell() method to fetch the value of the texturePath property

 specified in the WFS file and set the member variable, this.texturePath. Simply add the following line after the this.shapeType = .... line:
Line: 137 to 143
 

Loading the Texture on the Client

Changed:
<
<
Your !ShapeCell class that resides on the client-side needs modification--in fact, it's where all of the major changes go. First,
>
>
Your ShapeCell class that resides on the client-side needs modification--in fact, it's where all of the major changes go. First,
 add some imports that you'll need for later:
Line: 147 to 153
 import java.net.MalformedURLException;
Changed:
<
<
Next, you'll have to modify the setup() method. In this method, you'll have to perform the following additional tasks:
>
>
Next, you'll modify the setup() method. In this method, you'll perform the following additional tasks:
 
  1. Fetch the baseURL property from the ShapeCellSetup class.
  2. Fetch the texturePath property from the ShapeCellSetup class.
  3. Load the texture using the Wonderland client-side asset manager.
Changed:
<
<
  1. Create instances of the Java 3D Appearance and Texture objects
  2. Modify the creation of the Sphere and Box object to include your newly created Appearance.
>
>
  1. Create instances of the Java 3D Appearance and Texture objects.
  2. Modify the creation of the Sphere and Box object to include your newly-created Appearance.
  For the first two steps, you can add the following code beneath the initial SceneGraphUtil.setCapabilitiesGraph() call. Hopefully these steps should be self-explanatory.
Line: 180 to 186
 Next, load the texture using the Wonderland's asset manager. The asset manager checks whether the texture is already present in the local cache (via checksums) and uses the cached copy if so. Otherwise, it loads the texture from baseURL + "textures/" + texturePath. (The method automatically
Changed:
<
<
inserts the "textures/" part. This method returns an object of type !ImageComponent2DURL; it's a
>
>
inserts the "textures/" part). This method returns an object of type ImageComponent2DURL; it's a
 subclass of Java 3D's_ ImageComopnent2D?_ class, that is used to represent textures, among other things. Using this method to load the texture also automatically updates the window in Wonderland that pops up and displays the status of assets that are being download.
Line: 191 to 197
 In the fourth step, you will need to create two objects: an Appearance object and a Texture object that will control the appearance of your basic shapes. These two classes contain lots of configuration features to control the appearance of your
Changed:
<
<
shape. In this tutorial, you will simple set the texture for the shape. Please visit the complete Java 3D Documentation for more details about this API.
>
>
shape. In this tutorial, you will simply set the texture for the shape. It's beyond the scope of the tutorial to examine all of the options available in the Appearance and Texture classes. Please visit the complete Java 3D API Documentation for more details about this API.
 
        Appearance app = new Appearance();
Line: 201 to 208
  app.setTexture(tex);
Changed:
<
<
Finally, you will need to modify how you instantiate your Sphere and Box objects. You simple use a different constructor
>
>
Note: It may be required that the width and height of your image be a power of 2. (Our texture, MountainPicture.png has dimensions that are powers of 2). Please refer to the Java 3D API Documentation (specifically, the Texture2D for more details).

Finally, you will need to modify how you instantiate your Sphere and Box objects. You simply use a different constructor

 for each that now takes the Appearance object you just created. The remainder of your setup() method should look like this:
Line: 220 to 231
  }
Added:
>
>

Running With Your New Textured Shape

To recompile and re-run both the Wonderland server and client, in two separate terminal windows:

% ant run-sgs
% ant run

If you chose a Box to be displayed, your Wonderland world should look like this:

 

Next Steps

Changed:
<
<
In the next tutorial, you will learn how to texture your shape, enhancing its appearance. By using textures, you will learn how to interact with artwork repositories. Future tutorials will also explore how to receive notification of events (e.g. mouse clicks) for your cell and also manage and update the state of your cell shared among many clients.
>
>
In the next and final tutorial in this series, you will learn how your cell can capture keyboard and mouse input. Using it, you'll also learn how to synchronize the state of your cell among many clients.

 <<O>>  Difference Topic ProjectWonderlandNewCellPart3 (1 - 17 Jun 2008 - Main.jslott)
Line: 1 to 1
Added:
>
>
META TOPICPARENT name="ProjectWonderlandNewCellPart2"
Home | Changes | Index | Search | Go
<-- This creates the navigation links to :  Home | Help | Index | etc.  -->

Extending Project Wonderland by Creating New Cell Types - Part III

by Jordan Slott (jslott@dev.java.net)

<-- Your JavaDesktop? article goes here. Please try to include at least one sentence describing this topic. -->
<-- Also please try to include at least one sentence describing where each link goes. -->
<-- Please make sure some other page points to your new article so that others can find it! -->
<-- For more on how to write Javapedia articles please read the WritingArticles? page. -->

Purpose

In this tutorial, you will extend the simple new cell type you created in Part 1 and Part 2 of this tutorial series by texturing the basic geometric shape that is drawn in the cell. You will learn how to interact with the asset manager that comes part of the Project Wonderland client software to download the texture (a .png file) from the artwork repository.

This tutorial is designed for the v0.3 and v0.4 releases of Project Wonderland.

Expected Duration: 30 minutes

Prerequisites

Before completing this tutorial, you should have already successfully completed Part 1 and Part 2 of this tutorial series. You will be extending the functionality you implemented there.

Artwork Repositories

All artwork in Project Wonderland--whether they be geometric models that were created using a 3rd party modeling tool such as Maya Blender or textures creating using a standard graphics drawing package--are downloaded by the Wonderland client from a central artwork repository. The artwork that comes with the Project Wonderland demo world is available via a public art server at: http://192.18.37.42/trunk/lg3d-wonderland-art/compiled_models/. Go ahead and point your web browser to this URL, you should see directories containing the models and textures.

In this tutorial, you'll be texturing your basic shape with a picture of a mountain landscape (textures/default_building/MountainPicture.jpg). You may want to create your own image to use as a texture--in this case, you'll need to setup your own artwork repository. Please see these instructions on how to configure Wonderland to use your own artwork repository.

High-Level Design

You will enhance the custom shape cell to texture the sphere or box with an image from an artwork repository. This relative path (within the repository) of the texture will be specified in the cell's XML file within WFS. The path of the texture is then communicated to the client-side cell class that loads the image using the asset management facilities provided by Project Wonderland and then sets the shape's texture.

Adding Attributes to the ShapeCellSetup Class

First, you need to make some minor enhancements to the ShapeCellSetup class--this class, as you may recall, represents the cell type-specific configuration information that is communicated from the server to the client. In ShapeCellSetup.java, add the following two attributes near the top of the class:

    private String baseURL = null;
    private String texturePath = null;

Since this class follows the Java Bean pattern, you must also add the corresponding setter and getter methods for these two new properties:

    public String getBaseURL() {
        return baseURL;
    }
    
    public void setBaseURL(String baseURL) {
        this.baseURL = baseURL;
    }
    
    public void setTexturePath(String texturePath) {
        this.texturePath = texturePath;
    }
    
    public String getTexturePath() {
        return this.texturePath;
    }

The baseURL parameter gives the URL of the artwork repository. You do not set this within WFS, rather your server-side cell class (ShapeCellGLO) sets this parameter based upon Wonderland configuration files. The texturePath property gives the relative path of the texture file within the artwork repository.

Specifying the Texture Path in *shape-wlc.xml*

While we are on the subject of configuration, now's a good time to add the path of the texture to your shape-wlc.xml file in your WFS. Within the cellSetup property, beneath the entry for shapeType, add the following lines:

    <void property="texturePath">
      <string>default_building/MountainPicture.png</string>
    </void>

Note that this relative path excludes the textures directory parent--when you load this texture file via Wonderland's asset manager, it automatically prepends textures before the value of the texturePath property.

Modify the ShapeCellGLO Class

Changes to the server-side ShapeCellGLO class are relatively simple: you just need to store the texturePath property is a member variable and populate the ShapeCellSetup class when needed. First, add a member variable near the top of the class to store the texture path:

    private String texturePath = null;

Next, when you create a new !ShapeCellSetup class in the getSetupData() method, set the value of the texture path property from this class. You will also need to set the value of the baseURL property in the !ShapeCellSetup class. The value of this property is obtained from via the WonderlandConfig.getBaseURL() method. This method returns the value of the wonderland.art.url.base property (if using a remote artwork repository) or the wonderland.art.url.local property (if using an artwork repository stored locally on disk). (Strictly speaking, the CellGLO superclass contains a protected member variable called baseUrl with this value, however, this tutorial code calls WonderlandConfig.getBaseURL() directly to highlight where the value actually comes from).

Your getSetupData() method should now look like this:

    @Override
    public ShapeCellSetup getSetupData() {
        ShapeCellSetup setup = new ShapeCellSetup();
        setup.setShapeType(this.shapeType);
        setup.setBaseURL(WonderlandConfig.getBaseURL());
        setup.setTexturePath(this.texturePath);
        return setup;
    }

Finally, for the !ShapeCellGLO class, you need to modify the setupCell() method to fetch the value of the texturePath property specified in the WFS file and set the member variable, this.texturePath. Simply add the following line after the this.shapeType = .... line:

    this.texturePath = setup.getCellSetup().getTexturePath();

Loading the Texture on the Client

Your !ShapeCell class that resides on the client-side needs modification--in fact, it's where all of the major changes go. First, add some imports that you'll need for later:

import org.jdesktop.j3d.utils.scenegraph.ImageComponent2DURL;
import org.jdesktop.lg3d.wonderland.scenemanager.AssetManager;
import java.net.URL;
import java.net.MalformedURLException;

Next, you'll have to modify the setup() method. In this method, you'll have to perform the following additional tasks:

  1. Fetch the baseURL property from the ShapeCellSetup class.
  2. Fetch the texturePath property from the ShapeCellSetup class.
  3. Load the texture using the Wonderland client-side asset manager.
  4. Create instances of the Java 3D Appearance and Texture objects
  5. Modify the creation of the Sphere and Box object to include your newly created Appearance.

For the first two steps, you can add the following code beneath the initial SceneGraphUtil.setCapabilitiesGraph() call. Hopefully these steps should be self-explanatory.

    @Override
    public void setup(CellSetup setupData) {
        bg = new BranchGroup();
        bg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        bg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        SceneGraphUtil.setCapabilitiesGraph(bg, false);

        URL baseURL;
        String url = ((ShapeCellSetup) setupData).getBaseURL();
        try {
            baseURL = new URL(url);
        } catch (MalformedURLException ex) {
            System.err.println("Failed to load slide, bad baseURL " + url);
            return;
        }
        
        String texturePath = ((ShapeCellSetup)setupData).getTexturePath();

Next, load the texture using the Wonderland's asset manager. The asset manager checks whether the texture is already present in the local cache (via checksums) and uses the cached copy if so. Otherwise, it loads the texture from baseURL + "textures/" + texturePath. (The method automatically inserts the "textures/" part. This method returns an object of type !ImageComponent2DURL; it's a subclass of Java 3D's_ ImageComopnent2D?_ class, that is used to represent textures, among other things. Using this method to load the texture also automatically updates the window in Wonderland that pops up and displays the status of assets that are being download.

        ImageComponent2DURL ic = AssetManager.getAssetManager().createImageComponent2DURL(baseURL, texturePath);

In the fourth step, you will need to create two objects: an Appearance object and a Texture object that will control the appearance of your basic shapes. These two classes contain lots of configuration features to control the appearance of your shape. In this tutorial, you will simple set the texture for the shape. Please visit the complete Java 3D Documentation for more details about this API.

        Appearance app = new Appearance();
        Texture2D tex = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, ic.getWidth(), ic.getHeight());
        tex.setImage(0, ic);
        app.setTexture(tex);

Finally, you will need to modify how you instantiate your Sphere and Box objects. You simple use a different constructor for each that now takes the Appearance object you just created. The remainder of your setup() method should look like this:

        if (((ShapeCellSetup)setupData).getShapeType().compareTo("BOX") == 0) {
            Box box = new Box(1, 1, 1, Box.GENERATE_TEXTURE_COORDS, app);
            SceneGraphUtil.setCapabilitiesGraph(box, false);
            bg.addChild(box);
        }
        else if (((ShapeCellSetup)setupData).getShapeType().compareTo("SPHERE") == 0) {
            Sphere sphere = new Sphere(1, Sphere.GENERATE_TEXTURE_COORDS, app);
            SceneGraphUtil.setCapabilitiesGraph(sphere, false);
            bg.addChild(sphere);
        }
        cellLocal.addChild(bg);
    }

Next Steps

In the next tutorial, you will learn how to texture your shape, enhancing its appearance. By using textures, you will learn how to interact with artwork repositories. Future tutorials will also explore how to receive notification of events (e.g. mouse clicks) for your cell and also manage and update the state of your cell shared among many clients.


Topic ProjectWonderlandNewCellPart3 . { View | Diffs r7 < r6 < r5 < r4 | More }
 XML java.net RSS