ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 扩展WONDERLAND项目——创建新的单元类型(一)

扩展WONDERLAND项目——创建新的单元类型(一)

原创 Linux操作系统 作者:Java006 时间:2009-01-06 09:49:32 0 删除 编辑

By Yuanxin Li

目的

在这个例程中,你将开始学习如何在Wonderland项目里创建一个新的单元类型。单元是一个3D卷;创建新的单元类型的主要意义是开发者扩展Wonderland的功能。这个例程是五个例程中的第一个。在这个第一个例程中,你将学会如何编写一个组成新的单元类型的重要类,以及如何通过WFS在世界里创建一个实例。

这个例程是为Wonderland项目的v0.3和v0.4版本设计的。

预备知识

在开始这个例程之前,你应该首先成功下载和编译Wonderland项目。关于下载和运行Wonderland的说明可以在这里找到。你需要下载和编译主要的Wonderland工作区(lg3d-wonderland)以及可选的模块工作区(wonderland-modules)。wonderland-modules工作区提供了编译你的新单元类型的必要框架。

另外,在你开始学习这个例程之前,你还需要熟悉Wonderland的架构(这里)以及Wonderland文件系统WFS的元素(查看这个例程)。

单元架构

Wonderland里面的可见3D基础构建块被称为单元cells,由服务器端和客户端组成(图1)

 

服务器端由一个单独的类(MyCellGLO,图1)组成,这个类维护了世界中各个客户端参与者之间的共享状态。它有一个“GLO”的后缀,表明它是一个参与Darkstar游戏引擎机制的一个特别的对象。客户端(MyCell,图1)负责在世界里通过加载一个模型资源或者使用Java3D API直接描绘对象来渲染单元。单元的实例通过一个包含XML格式的单元描述文件——WFS(mycell-wlc.xml)来加载到世界当中,这个文件提供了一个单元的可配置参数的值。

Shape单元:一个新的单元类型

在这个例程中,你将学会如何在世界里创建一个描绘3D形状的新的单元类型。形状的类型(方形还是圆形)是通过WFS里的XML格式化的单元描述文件里的一个参数设置的。

设置好你的构建环境

如果你还没有做好,你需要下载和编译好lg3d-wonderland和wonderland-modules这两个工作区。这个例程假设你对Netbeans IDE很熟悉——因为Netbeans的编译机制是基于ant的,你也可以使用其他使用ant来构建工程的IDE来完成这个例程,或者你也可以使用命令行工具。

当你编译好你的工作区后,在Netbeans提供过文件->打开项目 来打开wonderland-modules工作区。

1、在Netbeans窗口的左上方点击打开“文件”视图。
2、展开节点以使wonderland-modules/src/modules/apps/3d路径被完全展开。
3、在3d文件夹里面,单击右键,选择 新建-文件夹,在文件夹名称中输入shapecell,点击完成。

在你的新文件夹中,你将创建两个文件:build.xml和project.xml。

1、在shapcell文件夹中,单击右键选择新建-其他。
2、在对话框中选择 其他-空文件,点击下一步。
3、将文件命名为build.xml,点击完成。

复制以下XML文件到你的build.xml文件中,并且保存:

 

   
   

    <!-- Use my-build.properties to override default values in build.properties -->
   

    <!-- set the project name -->
   

    <!-- import the common build attributes -->
   
    
    <!-- the name of the client jar file -->
   
    
    <!-- all files that should be built as part of the client jar file -->
   
       
       
   

   
    <!-- the name of the server jar file -->
   
    
    <!-- all files that should be built as part of the server jar file -->
   
       
       
   

    
    <!-- extra classes for compiling the server -->
    <!-- -->
      
    <!-- copy targets so NetBeans will recognize them -->
   
   
   
    
    <!-- You can override default methods to add functions at various
         points.  See module-common.xml for more information:
         
         -pre-init: before init
         -post-init: after init
         -pre-compile-client: before compiling client
         -post-compile-client: after compiling client
         -pre-compile-server: before compiling server
         -post-compile-server: after compiling server
         -pre-jar-client: before jar client
         -post-jar-client: after jar client
         -pre-jar-server: before jar server
         -post-jar-server: after jar server
         -pre-clean: before clean
         -post-clean: after clean
    -->
     
   
                       debuglevel="${build.debuglevel}"
               deprecation="${build.showdeprecation}" 
               destdir="${module.classes.dir}" 
               srcdir="${module.javasrc.dir}"
               nowarn="true" 
               source="1.5" 
               target="1.5">
           
               
           

       

   


下一步,你将创建project.xml文件,这个文件将帮助你创建一个Netbeans工程。

1、右键单击shapecell文件夹,选择新建-文件夹,将其命名为nbproject,点击完成。
2、在nbproject子文件夹中,创建一个空白文件并命名为project.xml,拷贝以下代码并保存:

 

    org.netbeans.modules.ant.freeform
   
       
            shapecell
       

       
            <!-- Do not use Project Properties customizer when editing this file manually. -->
            shapecell
           
                nbproject/nb.properties
           

           
               
                   
                    java
                    src/classes
                    UTF-8
               

               
                   
                    .
                    UTF-8
               

           

           
               
                    jar
               

               
                    clean
               

               
                    javadoc
               

               
                    clean
                    jar
               

           

           
               
                   
                       
                        src/classes
                   

                   
                        build.xml
                   

               

               
                   
                   
                   
                   
               

           

           
                ../../../../../../lg3d-wonderland
           

       

       
           
                src/classes
                ${wonderland.client.classpath}:${wonderland.server.classpath}
                1.5
           

       

   


 源代码包结构

当你的项目和ant文件建立好以后,你就可以创建放置源代码的目录了。每个单元的源代码被分为3个包:client,common以及server。client包里面的类将会编译到Wonderland的客户端中,server包里面的类将会被编译到Wonderland服务器中,而common包里面的类将会同时编译到服务器和客户端中。

1、右键单击shapecell文件夹,选择新建-文件夹,命名为src/classes,点击完成。
2、在classes文件夹节点中单击右键选择新建-Java包,命名为org.jdesktop.lg3d.wonderland.shapecell.client。
3、在classes文件夹节点中单击右键选择新建-Java包,命名为org.jdesktop.lg3d.wonderland.shapecell.common。
4、在classes文件夹节点中单击右键选择新建-Java包,命名为org.jdesktop.lg3d.wonderland.shapecell.server。

ShapeCellGLO服务器类

首先你需要创建服务器端的类来表示这个单元,ShapeCellGLO。这个服务器端类的目的是储存由WFS里的XML单元描述文件定义的基础配置信息。它同时为所有客户端管理单元的共享状态。为了帮助管理客户端的状态,包括单独的,同步的更新状态,ShapeCellGLO类应该参与到Darkstar事务型游戏架构的机制中。然而,在这个第一个例子里,ShapeCellGLO并不与其他客户端共享状态,而且不使用Darkstar的事务机制。(在以后的例子中会加入这些功能。)

1、右键单击server文件夹,选择新建-Java类,命名为ShapeCellGLO,点击完成。

Netbeans会创建一个类的架构,类似:

package org.jdesktop.lg3d.wonderland.shapecell.server;

public class ShapeCellGLO {
}

首先,拷贝这些适当的导入语句到你的Java类中(在package语句后)

import org.jdesktop.lg3d.wonderland.darkstar.server.cell.*;
import org.jdesktop.lg3d.wonderland.darkstar.server.setup.*;
import org.jdesktop.lg3d.wonderland.shapecell.common.ShapeCellSetup;
import javax.media.j3d.*;

下一步,修改你的Java类定义为:

public class ShapeCellGLO extends StationaryCellGLO implements BeanSetupGLO {

这个类继承了org.jdesktop.lg3d.wonderland.darkstar.server.cell 包中的StationaryCellGLO类,这个类是所有固定单元的基类,它自身继承了CellGLO类。ShapeCellGLO是Darkstar上下文的一个“托管对象”,因为CellGLO类实现了ManagedObject接口。ShapeCellGLO类同时实现了BeanSetupGLO接口,以及它的三个方法:setupCell(),reconfigureCell(), 以及 getCellGLOSetup()。 你将很快实现这三个方法。

ShapeCellGLO类维护了一个可配置的信息:一个描述描绘该形状的字符串:BOX或者SPHERE。你将在ShapeCellGLO里储存这个字符串:

 private String shapeType = null;

CellGLO类声明了一个虚函数,getSetupData,你必须实现它。这个方法应该返回一个表示你的单元可配置数据类的一个实例(其自身是CellSetup的一个子类)。在这里,你可以简单地创建和返回ShapeCellSetup的一个新的实例:

@Override
    public ShapeCellSetup getSetupData() {
        ShapeCellSetup setup = new ShapeCellSetup();
        setup.setShapeType(this.shapeType);
        return setup;
    }

实现BeanSetupGLO类的方法如下:

    public void setupCell(CellGLOSetup setupData) {
        super.setupCell((BasicCellGLOSetup) setupData);
        
        BasicCellGLOSetup setup = (BasicCellGLOSetup)setupData;
        this.shapeType = setup.getCellSetup().getShapeType();
        
        /* Setup bounds based upon shape of the object */
        if (this.shapeType.compareTo("BOX)") == 0) {
            super.setBounds(new BoundingBox());
            
        }
        else if (this.shapeType.compareTo("SPHERE") == 0) {
            super.setBounds(new BoundingSphere());
        }
    }

setupCell()方法在ShapeCellGLO类的实例被创建(用于初始化单元的可配置参数)时被调用。这些可配置参数通常是在WFS里的XML单元描述文件设置的——如何配置这个文件将会在稍后讨论。这个方法传递了实现CellGLOSetup接口的一个类,同时也是一个BasicCellGLOSetup类的一个实例。BasicCellGLOSetup类储存了所有单元类型的共同信息——原点,旋转,缩放以及范围。新的单元类型不需担心存储这些可配置的参数——StationaryCellGLO类通过自己的setupCell()方法处理好这些参数。

 BasicCellGLOSetup类有一个自己的成员(称为cellSetup),一个将参数储存到你的新的单元类型中的类。你将在稍后定义这个类(ShapeCellSetup)。ShapeCellSetup类存储了形状的类型——你将使用这个值来初始化ShapeCellGLO类里面的shapeType字符串。同时,你还需要使用它来适当地初始化单元的范围。

下一步,实现reconfigureCell() 和 getCellGLOSetup() 方法。reconfigureCell()方法在服务器运行的过程中,WFS里的XML单元描述文件被改变时被调用。我们先不实现这个方法,稍后会回来定义它:

public void reconfigureCell(CellGLOSetup setupData) {
    }

getCellGLOSetup() 方法返回了一个新的BasicCellGLOSetup类的对象(由ShapeCellSetup类设置其参数):

    public CellGLOSetup getCellGLOSetup() {
        return new BasicCellGLOSetup(getBounds(),
            getOrigin(), getClass().getName(), getSetupData());
    }

最后,实现getClientCellClassName() 方法。这个方法返回客户端单元类的全称类名(稍后会实现它):

    @Override
    public String getClientCellClassName() {
        return "org.jdesktop.lg3d.wonderland.shapecell.client.ShapeCell";
    }

ShapeCellSetup公共类

下一步,你将实现ShapeCellSetup类,这个类将编译到服务器端和客户端中。这个类遵循Java Bean的模式,简单的作为将可配置信息从服务器传递到客户端的容器。

1、右键单击common包,选择新建-Java类,命名为ShapeCellSetup,点击完成:

package org.jdesktop.lg3d.wonderland.shapecell.common;

import org.jdesktop.lg3d.wonderland.darkstar.common.CellSetup;

public class ShapeCellSetup implements CellSetup {

    private String shapeType = null;

    public ShapeCellSetup() {}
    
    public String getShapeType() {
        return shapeType;
    }

    public void setShapeType(String shapeType) {
        this.shapeType = shapeType;
    }
}

这个类以字符串的形式存储形状的类型,提供了一个默认的构造方法以及标准的get和set的方法。如果你希望对单元形状类型的功能进行扩展,例如包含一个半径或者颜色等可配置的参数,你也可以在这个类中包含这些新的参数。

ShapeCell客户端类

最后,你将实现ShapeCell客户端类,这个类负责在世界中描绘形状。

1、右键单击client包,选择新建-Java类,命名为ShapeCell。

实现为:

package org.jdesktop.lg3d.wonderland.shapecell.client;

import javax.media.j3d.*;
import com.sun.j3d.utils.geometry.*;
import javax.vecmath.Matrix4d;
import org.jdesktop.j3d.util.SceneGraphUtil;
import org.jdesktop.lg3d.wonderland.darkstar.client.cell.Cell;
import org.jdesktop.lg3d.wonderland.darkstar.common.*;
import org.jdesktop.lg3d.wonderland.shapecell.common.ShapeCellSetup;

public class ShapeCell extends Cell {

    public ShapeCell(CellID cellID, String channelName, Matrix4d origin) {
        super(cellID, channelName, origin);
    }
    
    @Override
    public void setup(CellSetup setupData) {
        BranchGroup bg = new BranchGroup();
        bg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        bg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        SceneGraphUtil.setCapabilitiesGraph(bg, false);
            
        if (((ShapeCellSetup)setupData).getShapeType().compareTo("BOX") == 0) {
            Box box = new Box();
            SceneGraphUtil.setCapabilitiesGraph(box, false);
            bg.addChild(box);
        }
        else if (((ShapeCellSetup)setupData).getShapeType().compareTo("SPHERE") == 0) {
            Sphere sphere = new Sphere();
            SceneGraphUtil.setCapabilitiesGraph(sphere, false);
            bg.addChild(sphere);
        }
        cellLocal.addChild(bg);

    }    
}

ShapeCell类继承Cell类,Cell类提供了客户端单元的基本功能。每个子类必须覆盖setup()方法来获取服务器端的配置信息,并且在世界中描绘单元。在这里,CellSetup对象是ShapeCellSetup类的一个实例。使用指定的形状类型,setup()方法描绘了一个盒子或者球(半径为1)。


在世界中创建一个形状单元

要在世界中创建你的新形状单元类型的一个实例,你可以在你世界的WFS中创建一个XML单元描述文件。在这个例程中,你将创建一个只包含这个单元的WFS,然而,你可以随意地放置许多个这个单元到已有的世界中去。

1、编辑lg3d-wonderland目录下的build.properties文件。将wonderland.wfs.root属性设置为${src.dir}/worlds/shape-wfs。
2、在${src.dir}/worlds 目录下(一般是lg3d-wonderand/src/worlds/)中创建shape-wfs 目录。
3、在shape-wfs 目录下,创建一个名为shape-wlc.xml 的文件。

将以下内容拷贝到你的shape-wlc.xml 里并保存:

 
 
 
   
   org.jdesktop.lg3d.wonderland.shapecell.server.ShapeCellGLO 
 
 
   
    
     
     SPHERE 
   
 
  
 
 
 
   
    
    50.0 
  
 
    
    2.0 
  
 
  
    40.0
  

 
 
 

这个文件根据Java Bean持久化机制(JSR-57, 查看http://java.sun.com/products/jfc/tsc/articles/persistence3/)来格式化。它包含了BasicCellGLOSetup类中所有的单元属性(在这里是其原点),以及在cellGLOClassName 属性中指定了要创建的单元的名称。像之前讨论的那样,BasicCellGLOSetup包含了一个成员,cellSetup,包含了特定的单元类型配置信息。在这里,我们将这个成员描述为一个ShapeCellSetup 类的实例,这个类只有一个属性,shapeType ——用于存储要描绘的形状。

形状的原点被设为(x, y, z) = (50.0, 2.0, 40.0) 一遍让这个球出现在我们的初始位置前。

编译、运行

lg3d-wonderland的一个很好的特性是,它会自动地查找和编译wonderland-modules目录。事实上,为了正确地编译你的模块(以便类路径被正确包含所有Wonderland相关的JAR包),你必须从lg3d-wonderland目录里编译。要编译和运行你的新类型,在命令行工具里运行:

% cd lg3d-wonderland
% ant run-sgs

(注意:在日至文件中,你可能会看见一些警告信息:aliases.xml和version.xml文件丢失。这些警告消息是无害的,这个两个文件的功能有待实现。)

在另外一个命令行工具中,运行:

% cd lg3d-wonderland
% ant run

Wonderland客户端出现并登陆后,你应该可以在你面前看到一个黑色的球:

 

额外尝试

如果你希望扩展一下这个新的单元类型,你可以使用这个对象的半径或颜色的配置。这些改变会包含在客户端和服务器端的类,ShapeCellSetup 以及相应的XML单元描述文件中。你可能需要添加其他类型的形状的支持,例如立方体,圆锥等,这些基础的类型可以从Java3D 中获得,你可以自由地进行实验。

下一步

在下一个例程中,你将学习如何在运行时处理你的单元类型的可配置参数的改变。在将来的一些例程中,你还会学习如何为你的形状添加材质,改善它的外观等。在使用材质的时候,你还会学习如何与模型库交互。在将来的例程中,你还会学习如何如何接收事件,在很多客户端中管理和更新你的单元的共享状态。

第二部分:动态处

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14734416/viewspace-528445/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-07-07

  • 博文量
    122
  • 访问量
    554591