首页 | CG软件 | CG信息 | CG教程 | 三维作品 | 设计理论 | CG加油站 | 设计鉴赏 | 社区图库 | Flash | 专题 | 顶客 | 论坛 | 博客 | 导航 | 下载 | 高级搜索
RSS
热门: 素材  作品  设计  效果图  创意  3dsmax  优秀作品  Vray  艺术  欣赏

JAVA3D学习系列

来源: 作者:图腾收集 时间:2007-12-05 点击:
系列   学习   Java    PIII、K6-III出来了,在3D编程语言中,JAVA3D也应占有重要的位置。
  为此,本人拿出半年多学习及应用JAVA3D的经验,借国内主要BBS站点,推出JAVA3D编
程指导,并给出大量的例子。
  一。如何运行JAVA3D?
  只要在WIN95/98上安装了JDK1.2(JAVA2),再安装JAVA3D运行环境,就可以运行JAV
A3D,注重,别忘了在autoexec.bat中插入一行:
  SET PATH=C:\JDK1.2\BIN
  目前我们可以从SUN公司的站点获得最新的JAVA3D,本人拥有的为:
  java3d1_1-win32-opengl-jdk.exe,大小为3197K。
  JAVA3D运行环境中附有许多例子,可用来学习JAVA3D,同时网络上还有大量的JAVA3D
学习资料,可以用来学习JAVA3D编程。
  二。网络上的JAVA3D学习资料
  1http://www.sun.com/desktop/java3d/collateral/
  这里有SUN公司为我们提供的学习资料。
  2http://www.sdsc.edu/~nadeau/Courses/VR99/java3d.zip
  这是一个非常好的JAVA3D学习资料。(12,058K),里面有许多例子。
  大家可以http://www.sdsc.edu/~nadeau/中得到VRML和JAVA3D的许多资料。
  一。JAVA3D的作用:
  JAVA3D可用在三维动画、三维游戏、机械CAD等领域。
  1.可以用来编写三维形体,但和VRML不同,JAVA3D没有基本形体,不过我们可以利用
JAVA3D所带的UTILITY生成一些基本形体如立方体、球、圆锥等,我们也可以直接调用一些
软件如ALIAS、LIGHTWARE、3DS MAX生成的形体,也可以直接调用VRML2.0生成的形体。

  2.可以和VRML一样,使形体带有颜色、贴图。
  3.可以产生形体的运动、变化,动态地改变观测点的位置及视角。
  4.可以具有交互作用,如点击形体时会使程序发出一个信号从而产生一定的变化。

  5.可以充分利用JAVA语言的强大功能,编写出复杂的三维应用程序。
  6.JAVA3D具有VRML所没有的形体碰撞检查功能(这也是本人目前中意JAVA3D的原因)

  (作为一个高级的三维图形编程API,JAVA3D给我们带来了极大的方便,它的作用可以
说,几乎包含了VRML2.0所提供的所有功能。)
  二。OPENGL、VRML、DIRECT3D、JAVA3D的比较
  由于OPENGL的跨平台特性,许多人利用OPENGL编写三维应用程序,不过对于一个非计
算专业的人员来说,利用OPENGL编写出复杂的三维应用程序是比较困难的,且不说C(C++
)语言的把握需要花费大量时间精力,当我们需要处理复杂问题的时候,我们不得不自己
完成大量非常繁琐的工作。当然,对于编程高手来说,OPENGL是他们发挥才能的非常好的
工具。
  VRML2.0(VRML97)自1997年12月正式成为国际标准之后,在网络上得到了广泛的应用,
编写VRML程序非常方法(VRML语言可以说比BASIC、JAVAs cript等语言还要简单),同时可
以编写三维动画片、三维游戏、用于计算机辅助教学,因而其应用前景非常广阔尤其适合
在中国推广应用。不过由于VRML语言功能目前还不是很强(如目前没有形体之间的碰撞检
查功能),与JAVA语言等其它高级语言的连接较难把握,因而失去了一些计算机高手的宠
爱。但我们认为,我们可以让大学里的文理科学生利用VRML编写多媒体应用程序,让学生
很快地对编写程序感爱好,从而使国内的计算机水平得到提高。
  DIRECT3D是Microsoft公司推出的三维图形编程API,它主要应用于三维游戏的编程,
目前相关的学习资料难于获得,由于它一般需要VC等编程工具进行编程,需要编程人员具
有较高的C++等高级语言的编程功底,因而难以普及。
  JAVA3D是建立在JAVA2(JAVA1.2)基础之上的,JAVA语言的简单性使JAVA3D的推广有了
可能。OPENGL和JAVA3D之间的比较可以看成汇编语言与C语言之间的比较,一个是低级的,
一个是高级的(也许这样比较不太恰当)。JAVA3D给我们编写三维应用程序提供了一个非
常完善的API,它可以帮助我们:
  生成简单或复杂的形体(也可以直接调用现有的三维形体)
  使形体具有颜色、透明效果、贴图。
  可以在三维环境中生成灯光、移动灯光。
  可以具有行为(Behavior)的处理判定能力(键盘、鼠标、定时等)
  可以生成雾、背景、声音等。
  可以使形体变形、移动、生成三维动画。
  可以编写非常复杂的应用程序,用于各种领域如VR。
  三。如何获得JAVA3D运行环境
  http://java.sun.com/products/java-media/3D/我们可以获得最新的JAVA3D运行环
境,目前最新的版本是1.1.1,在安装之前需要安装jdk1.2。
  JAVA3D学习系列(二)
  BBS 水木清华站vrml
  在编写JAVA3D程序之前,我们需要了解一些概念,完成一些预备工作。
  一. JAVA3D的数据结构
  JAVA3D实际上是JAVA语言在三维图形领域的扩展,JAVA3D的编程和JAVA一样,是面向
对象的编程。
  JAVA3D的数据结构采用的是Scene Graphs Structure(场景图),这一灵活的树状结
构与显示列表多少有些相似之处,但运用起来更耐用(More Robust)。JAVA3D的场景图是
DAG(Directed-acyclic Graph),即具有方向性的不对称图形。
  场景图中有许多线和线的交汇点,交汇点称为节点(Node),不管什么节点,它都是
JAVA3D类的实例(Instance of Class)线(Arc)表示实例之间的关系。
  在JAVA3D的场景图中,最底层(根部)的节点是Virtual Universe,每一个场景图只
能有一个Virtual Universe。
  在Virtual Universe上面,就是Locale节点,每个程序可以有一个或多个Locale,但
同时只能有一个Locale处于显示状态,就好象一个三维世界非常大,有很多个景点,但我
们同时只能在一个景点进行观察。当然我们可以从一个景点跳到另一个景点,不过绝大多
数程序只有一个Locale。
  每一个Locale上面拥有一个到多个BranchGroup节点。我们知道,要想建立我们的三维
应用环境,我们必须建立所需要的形体(Shape),给出形体的外观(Appearance)及几何
信息(Geometry),再把它们摆放在合适的位置,这些形体及其摆放位置都建立在Branch
Group节点之上,摆放位置通过另一个节点TransformGroup来设定。另外,我们在安放好三
维形体之后,还需要设定具体的观察位置,我们暂时用View Platform代替,它也是建立在
TransformGroup节点之上的。
  下面我们用一个示意图来说明上面我们介绍的JAVA3D的场景图概念。
        Virtual Universe
            |
            |----------------------------------|
            |                  |
           Locale              Locale
            |
            |
    ----------------+-----------------
    |    |        |    |
    |    |        |    |
    BG   BG       BG    BG  (BG--BranchGroup)
    |    |        |    |
    |    |        |    |   (S---Shape)
    S    TG       TG    TG   (TG--TransformGroup)
  ----+---  |        |    |
  |    |  |        |    |
  A    G  S        S    View Platform
        |        |
        |        |        (A---Appearance)
      ----+----    ----+----      (G---Geometry)
      |    |    |    |
      |    |    |    |
      A    G    A    G

  JAVA3D学习系列(三)
  BBS 水木清华站vrml
  一. 如何安装JAVA3D
  下载JDK1.2及JAVA3D (目前最新的为1.1.1版本)。
  在WIN95/98上安装,先安装JDK1.2,再安装JAVA3D,将JDK安装到JDK1.2目录下。
  建立一个自己的目录,在自己的目录中编写并运行程序。
  注重,安装JDK1.2时别忘了在autoexec.bat中插入一行:
  SET PATH=C:\JDK1.2\BIN
  JDK1.2的大小为20,041KB(jdk12_win32.exe)。
  JAVA3D的大小为3,197KB(java3d1_1-win32-opengl-jdk.exe)
  安装时可以选择所有缺省参数以减收麻烦。
  二. 如何编写JAVA3D源程序
  用自己喜爱的文本编辑工具编辑源程序,和其它JAVA程序一样,程序后缀为JAVA。

  三. 如何运行JAVA3D源程序
  用JAVAC编译源程序,生成class文件。根据文件的类型,选择用JAVA或APPLETVIEWER
运行程序。
  JAVA3D程序可以为APPLICATION程序,也可以为APPLET程序,因而JAVA3D程序也可以摆
放在网页上,当然这时候我们必须在浏览器上做一些设置工作(以后再介绍)。
  四. 一个最简单的JAVA3D源程序。
  下面我们介绍一个最简单的JAVA3D源程序,进而介绍JAVA3D为我们提供的各种功能。

  程序是一个JAVA的APPLET类型的程序,它的作用是显示一个红色的圆锥,仅此而已。

  名为SimpleCone.java。
  //SimpleCone.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  //import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.geometry.Cone;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class SimpleCone extends Applet{
  public BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objTrans = new TransformGroup();
  objRoot.addChild(objTrans);
  Appearance app = new Appearance();
  Material material = new Material();
  material.setEmissiveColor(new Color3f(1.0f,0.0f,0.0f));
  app.setMaterial(material);
  Cone cone=new Cone(.5f,1.0f,1,app);
  objTrans.addChild(cone);
  objRoot.compile();
  return objRoot;
  }
  public SimpleCone() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  //public static void main(String[] args) {
  //new MainFrame(new SimpleCone(), 256, 256);
  //}
  }
  //end of Simple.java
  在运行applet程序时,我们需要编写一个HTML文件:
  
  
  
  

  
  
  先用javac将JAVA3D源程序编译成class文件,再用appletviewer运行HTML文件。
  虽然程序是applet程序,但我们也可以将其变成application程序,这时我们只需将程
序头尾的四个注释行的注释符号去掉即可,这时我们可以用java来运行它:
  java SimpleCone
  JAVA3D学习系列(四)
  BBS 水木清华站vrml
  JAVA3D程序也是JAVA程序,因而我们首先必须对JAVA有所了解,并能编写简单的JAVA
程序,了解JAVA编程的基本概念,关于JAVA语言的相关知识,我们在这里就不一一介绍了
,国内这方面的书籍非常丰富。
  一. SimpleCone程序分析
  1. SimpleCone.java及其对应的VRML程序
  上一节中,我们给出了SimpleCone这个非常简单的JAVA3D程序,下面我们来解读这个
程序,进而介绍JAVA3D所提供的API的内容。
  第三节中,我们对JAVA3D的场景图结构作了一个简单的介绍,从场景图我们可以看出
,JAVA3D的场景图和VRML的场景图非常相似,因而我们可以编写类似的VRML程序出来,与
JAVA3D程序进行比较。
  SimpleCone程序只是显示一个红色的圆锥,相类似的VRML程序为:
  //SimpleCone.wrl
  #VRML V2.0 utf8
  Shape{
  geometry Cone{ bottomRadius .5 height 1.0}
  appearance Appearance{material Material{emissiveColor 1 0 0}}
   }
  //end of SimpleCone.wrl
  可以看到,与JAVA3D程序相比,VRML程序要简单的多,并且可以直接在IE和Netscape
浏览器上运行,而JAVA3D则要复杂的多。不过几乎所有的VRML程序都可以用JAVA3D编写出
来,而稍微复杂一点的JAVA3D的程序则基本上无法用VRML语言完成。因为VRML几乎可以看
成是一个三维计算机图形格式,而JAVA3D则是一个高级计算机语言。
  在上面的VRML程序中,只定义了一个三维形体及其材质,背景、灯光、位置等均为缺
省值。
  同样地,SimpleCone.java程序中,我们也只定义了三维形体及其材质,没有背景、灯
光等,处在缺省的位置上(坐标系原点)。
  JAVA3D和VRML一样,采用的是一个符合右手螺旋法则的三维坐标系。正X轴向右,正Y
轴向上,正Z轴朝外(从计算机屏幕指向我们)。
  2. JAVA3D(API)中的类
  JAVA3D是SUN公司为我们提供的一个API,里面包含了几乎所有我们所需要的编写JAVA
三维多媒体应用程序的基本的类及方法。我们在编程时,只需调用所需要的类及方法,就
可以快速地编写出复杂的三维多媒体应用程序。可以说,我们所做的工作只是学会应用JA
VA3D的各种类(Objects)及方法。
  JAVA3D为我们提供了100多个存放于javax.media.j3d程序包中的类,它们被称为JAVA
3D的核心类,除了核心包中的类以外,JAVA3D还提供了一些其它程序包,其中一个重要的
包是com.sun.j3d.utils包(Utility)。
  JAVA3D所提供的Utility并不是JAVA3D编译环境的核心组成部分,我们可以不用它,不
过使用它们会大大提高我们的程序编写效率。JAVA3D为我们提供的Utility会不断增加,例
如有可能增加处理NURBS曲线的Utility。目前,JAVA3D为我们提供了四组Utility,它们是

  用于调用其它三维图形格式如ALIAS图形格式的content loader
  用于构造场景图的scene graph construction aids
  用于建立一些基本体如圆锥、球的geometry classes
  一些其它方便我们编程的convenience utilities
  除了JAVA3D的核心包及Utility包之外,每个JAVA3D程序还必需用到下面两个包:jav
a.awt和javax.vecmath。java.awt包用来定义一个显示用的窗口,而javax.vecmath包则是
用来处理调用程序所需要的定义矢量计算所用的类,处理定义三维形体及其位置时,我们
需要用到点、矢量、矩阵及其它一些数学对象,它也是JAVA3D所提供的一个包,目前它在
JAVA3D的编译环境中,今后则可能会成为JAVA1.2的核心组成部分。
  根据其作用,JAVA3D所提供的类主要有两种类型:Node、NodeComponent
   Node类,它含有Group及Leaf两个子类:
   Group类(用于将形体等按一定的组合方式组合在一起),
  类似于VRML的组节点。
   Leaf 类(如Light、Sound、Background、shape3d、
   Appearance、Texture及其属性等,还有
   ViewPlatform、Sensor、Behavior、Morph、
   Link等),类似与VRML的相应节点,是JAVA3D
   场景图的重要组成部分。
   NodeComponent类,用于表示Node的属性,它并不是JAVA3D场景图
  的组成部分,而是被JAVA3D场景图所引用,如某
  一个颜色可以被多个形体所引用。
  3. SimpleCone.java程序import语句部分的介绍
  根据JAVA3D所提供的类,按照面向对象的编程方式,我们可以编写出三维环境中所需
要的各个对象。编写JAVA3D程序的要害是学会应用JAVA3D所提供的各个类,生成自己所需
要的对象。
  下面我们来看一下SimpleCone.java里的每一个import语句。
  我们知道,java程序中。凡是利用到的外部的类均用import语句调用,我们首先介绍
一下程序中的import语句。
  第一个import语句表示本程序是Applet程序。
  第二个import语句表示窗口环境采用BorderLayout治理方式。
  第三个import语句语句在去掉//后就可以使程序既为applet也为application,为此,
使用了JAVA3D所附带的一个Utility,这是一个名叫Jef Poskanzer的人所编写的类。
  第四个import语句表示调用生成Cone的一个Utility,这是因为,JAVA3D和VRML不同,
VRML有几个基本几何体的节点语句,但JAVA3D的核心部分一个基本体也没有定义,但JAVA
3D所附带的Utility为我们提供了一些事先编好的基本体,我们可以调用这些基本体。
  第五个import语句表示我们调用一些设置基本的观测位置所用的类,如SimpleUniver
se、Viewer、ViewingPlatform等,利用它们,我们可以很方便地构造JAVA3D场景图底部的
VirtualUniverse、Locale及其上的View分支,进而使精力主要用在建模及复杂问题的处理
上面,当然它们也都是JAVA3D所附带的Utility。
  第六个import语句表示调用程序所需要的JAVA3D核心类,因而所有JAVA3D程序都必须
带有这一语句,只有这样才能在JDK1.2环境中编译执行JAVA3D程序。
  第七个import语句表示调用程序所需要的定义矢量计算所用的类。
  3. SimpleCone.java程序的组成
  SimpleCone.java程序主要由三个部分组成:
   createSceneGraph方法的定义
   SimpleCone的构造函数
   用于生成application应用程序的main函数
  4. createSceneGraph方法的定义
  我们首先来看一下createSceneGraph方法的定义部分。通过第三讲的JAVA3D场景图的
简单示意图,我们知道,为了编写出一个JAVA3D应用程序,我们必须编写出一个拥有三维
形体的内容分支,即一个分支组,一个BranchGroup。我们将我们所需要的形体及其材质定
义在里面,由于一般形体会摆放在三维空间的某一个位置,因而我们还需要先在BranchGr
oup分支之上建立一个可用于几何变换用的TransformGroup,即几何变换分支组,再将形体
及其材质作为TransformGroup的一个分支给出,当然程序中假如将形体摆放在坐标原点,
也可以不给出一个TransformGroup,如下面的SimpleCone1程序运行起来和SimpleCone结果
完全一样,它没有一个TransformGroup对象:
  //SimpleCone1.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.geometry.Cone;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class SimpleCone1 extends Applet{
   public BranchGroup createSceneGraph() {
    BranchGroup objRoot = new BranchGroup();
    Appearance app = new Appearance();
    Material material = new Material();
    material.setEmissiveColor(new Color3f(1.0f,0.0f,0.0f));
    app.setMaterial(material);
    Cone cone=new Cone(.5f,1.0f,1,app);
    objRoot.addChild(cone);
    objRoot.compile();
    return objRoot;
   }
   public SimpleCone1() {
    setLayout(new BorderLayout());
    Canvas3D c = new Canvas3D(null);
    add("Center", c);
    BranchGroup scene = createSceneGraph();
    SimpleUniverse u = new SimpleUniverse(c);
    u.getViewingPlatform().setNominalViewingTransform();
    u.addBranchGraph(scene);
   }
   public static void main(String[] args) {
    new MainFrame(new SimpleCone1(), 256, 256);
   }
  }
  //end of SimpleCone1.java
  JAVA3D有三种运行方式,一种是Immediate Mode,一种是
  Retained Mode,一种是Compiled-Retained Mode。
  SimpleCone程序中的
  objRoot.compile();
  表示程序为Compiled-Retained Mode,在这种模式下,JAVA3D对程序进行了优化,程
序的运行运行速度最快。不过在一些场合,如形体在程序运行过程中才生成,则不能Comp
ile形体,这说明优化是有条件的。
   注重,JAVA3D程序没有“开始渲染”这一步骤,当一个View被有效地放入一个Virtu
al Universe,JAVA3D运行环境就开始不停地渲染JAVA3D场景图中的三维形体,从而使屏幕
上显示出三维图形。
  5. SimpleCone的构造函数
  SimpleCone的构造函数的作用为
   首先设置一个BorderLayout。
   生成一个名为c的Canvas--Canvas3D继续了JDK1.2中的Canvas类,从而构造了一个图
形环境。
   将c放入BorderLayout的中心位置。
   生成一个场景图分支scene,里面定义了形体及其材质(红色)。
   借用JAVA3D的一个Utility,生成了场景图的Virtual Universe及Locale、Viewer,
和VRML程序有些不同,在缺省情况下,JAVA3D的观察点为位于(0 , 0 , 2.41),而VRML
的观察点位于(0 , 0 , 10),因而形体在VRML中看起来比较小,而在JAVA3D中看起来比
较大。我们利用这个Utility生成的这个u使我们不必考虑生成场景图中的观测分支,不过
它也有缺点,即我们不能在Virtual Universe中拥有多个View,因而也就不能从一个View
跳到另一个View。
  6. 用于生成application应用程序的main方法
  为了使我们的程序既可以为applet程序,又可以为application程序,我们可以通过编
写一个main方法,利用import语句提供的MainFrame类,生成一个MainFrame对象,从而使
程序变成为application程序。MainFrame是JAVA3D为我们提供的一个非常有用的Utility。

  JAVA3D学习系列(五)
  BBS水木清华vrml
  介绍了一个简单的JAVA3D程序后,我们开始学习JAVA3D的编程技术。首席我们介绍三
维基本形体的生成。
  和VRML不同,JAVA3D没有基本形体类,因而在程序中无法直接生成大量应用的基本形
体,如BOX、CONE、SPHERE等。我们可以通过复杂的编程生成这些基本形体,也可以直接调
用JAVA3D为我们提供的geometry classes,利用它生成程序所需要的BOX、COLORCUBE、CO
NE、SPHERE、CYLINDER。下面介绍这些基本体的生成方法。
  一. BOX
  UTILITY里BOX的构造函数有:
  1.Box()
  生成一个各边尺寸均为2的BOX,要说明的是,BOX、COLORCUBE、SPHERE的坐标原点均
在其中心点,CONE、CYLINDER的则在其轴线的中点上。
  2.Box(float xdim, float ydim, Appearance ap)
  生成一个给定尺寸、给定外观属性的BOX
  例:Box(.5f, .6f, .4f, myApp)
  3.Box(float xdim, float ydim, float zdim, int primflags, Appearance ap)
  生成一个有特定说明的BOX,例如:
  Box(.4f,.6f,.3f,Primitive.ENABLE_APPEARANCE_MODIFY, ap)
  表示程序在运行时可以改变其外观属性。
  我们可以在程序中使用的primflags种类可以在JAVA3D所附带提供的UTILITY里的Prim
itive.java中获得。
  二. COLORCUBE
  UTILITY里COLORCUBE的构造函数有:
  1.ColorCube()
  生成一个边长均为2的COLORCUBE
  2.ColorCube(double scale)
  将边长均为2的COLORCUBE按比例放大缩小。
  三. CONE
  UTILITY里CONE的构造函数有:
  1.public Cone()
  生成一个底半径为1,高为2的CONE。
  2.Cone (float radius, float height)
  3.Cone (float radius, float height, int primflags, Appearance ap)
  4.Cone(float radius, float height, int primflags, int xdivision, int ydivi
sion, Appearance ap)
  这里,xdivision、ydivision可用来表示圆锥的显示是高精度的显示,或是底精度的
显示,缺省时的中等精度时xdivision = 15; ydivision = 1; 我们可利用这两个参数来改
变显示的效果,使显示圆锥的三角片更多或更少些。
  四. SPHERE
  UTILITY里SPHERE的构造函数有:
  1.Sphere()
  生成一个半径为1的SPHERE。
  2.Sphere (float radius)
  3.Sphere (float radius, Appearance ap)
  4.Sphere(float radius, int primflags, Appearance ap)
  5.Sphere(float radius, int primflags, int divisions)
  6.Sphere(float radius, int primflags, int divisions,
   Appearance ap)
  这里,divisions的作用和圆锥的xdivision、ydivision相似。
  五. CYLINDER
  UTILITY里CYLINDER的构造函数有:
  1.Cylinder()
  生成一个底半径为1,高为2的CYLINDER。
  2.Cylinder (float radius, float height)
  3.Cylinder (float radius, float height, Appearance ap)
  4.Cylinder (float radius, float height, int primflags, Appearance ap)
  5.Cylinder(float radius, float height, int primflags,int xdivision, int yd
ivision, Appearance ap)
  有了这些基本体的构造函数,我们就可以按SimpleCone.java程序同样的方法,编写出
生成BOX、COLORCUBE、CONE、SPHERE、CYLINDER的JAVA3D程序来。
  JAVA3D学习系列(六)--点的生成
  BBS水木清华张杰
  ( 在前面(第6部分)我们介绍了如何编写JAVA3D三维基本形体的)
  ( 程序,需要指出的是,我们将前面的SimpleCone.java程序修改为)
  ( 其它形体时,我们需要同时修改import语句的类型,或者干脆将)
  ( 相应的那个import语句修改成:)
  ( import com.sun.j3d.utils.geometry.*; )
  JAVA3D编程过程中,我们经常要编写一些点、线、面,JAVA3D所提供的API中有许多这
方面的对象,下面我们开始一一介绍它们的使用方法。
  一. 点的生成
  我们先用VRML编写一个带有不同颜色的六个点的程序。
  //Point.wrl----观测点在(0 0 10)
  #VRML V2.0 utf8
  Shape {
   geometry PointSet {
    coord Coordinate {
     point [.8 .8 .0, -.8, .8 0, .5 0 0,
         -.5 0 0, -.8 -.8 0, .8 -.8 0]}
   color Color{
  color [ .0 .5 1., .5 .0 1, 0 .8 .2,
  1 0 .3, 0 1 .3, .3 .8 0 ]}
   }}
  #end of Point.wrl
  由程序可知,VRML程序中的点非常小,且无法变大。
  下面我们改用JAVA3D编写同样的程序,不过由于观测点不同,观测效果有差异,VRML
程序中的点比较集中,JAVA3D程序中的点比较分散,程序如下:
  //Point1.java-----观测点在( 0 0 2.41 )
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Point1 extends Applet {
  public BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,0.2f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  Shape3D shape = new Shape3D();
  PointArray point = new PointArray(6, PointArray.COORDINATES
  |PointArray.COLOR_3);
  point.setCoordinates(0,vert);
  point.setColors(0,color);
  shape.setGeometry(point);
  objRoot.addChild(shape);
  objRoot.compile();
  return objRoot;
  }
  public Point1() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Point1(), 400,400);
  }
  }
  //end of Point1.java
  我们来分析一下上面的Point1.java。
  我们知道,编写JAVA3D程序实际上是编写一个特定的场景图,给出了场景图中带有形
体及其属性的一个分支(BranchGrou)和表示观察位置等数据的另一个分支(View Platf
orm)。一般来说,表示观测位置的分支可以用JAVA3D的UTILITY来完成,因而我们可以看
到,在Point1.java中,构造函数Point1和前面介绍的SimpleCone.java的构造函数Simple
Cone内容完全一样。两个程序的不同之处在于形体构造及处理分支,即createSceneGraph
方法的定义。
  我们来看一下Point1.java的createScendGraph方法的定义。
  在这个方法里,程序先定义了一个分支objRoot,然后用数组的形式定义了六个顶点坐
标vert和六种颜色color,再用PointArray定义了一组点point,并将顶点坐标及颜色赋值
给point,由于JAVA3D中的PointArray点是Shape3D的子类,它不能直接放入一个BranchGr
oup,因而我们还要先定义一个Shape3D对象shape,再将point赋予shape,这样point就可以
放入BranchGroup类型的对象objRoot中了。
  二. PointArray、IndexedPointArray介绍
  JAVA3D提供的API中,可用于生成Point的对象有:
  PointArray
  IndexedPointArray
  1. PointArray
   PointArray的构造函数为:
   PointArray( int vertexCount, int vertexFormat );
   这里,vertexCount表示应生成的点的数目,
   vertexFormat表示所需要的顶点的格式。
   点、线、面几何体所需要的顶点的格式有:
   COORDINATES顶点坐标数组
   NORMALS顶点法向数组
   COLOR_3不带alpha值的颜色数组
   COLOR_4带alpha值的颜色数组
   TEXTURE_COORDINATE_2 二维纹理坐标数组
   TEXTURE_COORDINATE_3 三维纹理坐标数组
   Point1.java程序用到了COORDINATES和COLOR_3。
  2. IndexedPointArray
   IndexedPointArray的构造函数为:
   IndexedPointArray( int vertexCount, int vertexFormat,
  int indexCount );
   利用本函数,我们可以从众多的点中,选择特定的点来显示。
   这里,vertexCount表示顶点坐标数组所提供的点的总个数,
   indexCount表示最终应生成的点的个数。
  三. 20像素大小的点的生成
  JAVA3D可以生成任意大小的点,并且可以使点为方点或圆点。
  下面的程序生成了一个20像素大小的程序。
  //Point2.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Point2 extends Applet {
  public BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  Shape3D shape = new Shape3D();
  PointArray point = new PointArray(6, PointArray.COORDINATES
  |PointArray.COLOR_3);
  point.setCoordinates(0,vert);
  point.setColors(0,color);
  PointAttributes pa = new PointAttributes();
  pa.setPointSize(20.0f);
  pa.setPointAntialiasingEnable(true);
  //不加这一行,点的显示效果为正方形
  //加了这一行,点的显示效果为圆形
  Appearance ap = new Appearance();
   ap.setPointAttributes(pa);
  shape.setGeometry(point);
  shape.setAppearance(ap);
  objRoot.addChild(shape);
  objRoot.compile();
  return objRoot;
  }
  public Point2() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Point2(), 400,400);
  }
  }
  //end of Point2.java
  四. IndexedPointArray编写的点
  下面的程序中,我们用IndexedPointArray生成了四个点。
  //Point3.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Point3 extends Applet {
  public BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  Shape3D shape = new Shape3D();
  int[] index={ 0 , 2 , 3 , 4 };
  int VertexCount=4;
  IndexedPointArray point = new IndexedPointArray(6,
  IndexedPointArray.COORDINATES|
  IndexedPointArray.COLOR_3,
  VertexCount);
  point.setCoordinates(0,vert);
  point.setColors(0,color);
  point.setCoordinateIndices(0,index);
  point.setColorIndices(0,index);
  PointAttributes pa = new PointAttributes();
  pa.setPointSize(20.0f);
  pa.setPointAntialiasingEnable(true);
  Appearance ap = new Appearance();
   ap.setPointAttributes(pa);
  shape.setGeometry(point);
  shape.setAppearance(ap);
  objRoot.addChild(shape);
  objRoot.compile();
  return objRoot;
  }
  public Point3() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Point3(), 400,400);
  }
  }
  //end of Point3.java
  通过上面的程序,我们来看一下IndexedPointArray的应用方法。
  在定义一个point实例后,我们要给出顶点坐标数组及对应各个顶点的颜色数组,按下
标给出我们的顶点及颜色的具体选择方案。从而得以从众多的点中,选择特定的点来显示
并给定颜色。通过setPointSize、setPointAntialiasingEnable的设定,使显示的点拥有
一定的大小及良好的显示效果。
   ---1------0---
  ---3------2---
   ---4------5---
  程序Point3.java中,我们只选用了六个点中的0、2、3、4 四个点。
  五. 主程序比较简洁的程序Point4.java
  前面几个程序,所有的内容均放置在一个程序中,这对于阅读程序来说,增添了一些
困难。一般来说,一个具体的例子通常由几个JAVA3D程序来完成,一般是将形体生成部分
划为单独的一个子程序,下面我们将上面的Point3.java分成两个程序:子程序myShape.j
ava用来生成点,主程序Point4.java完成其它设置任务并调用myShape.java,我们设定两
个程序均位于同一个子目录下。
  //pointShape.java
  import javax.media.j3d.*;
  public class pointShape extends Shape3D {
  private float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  public pointShape() {
  int[] index={ 0 , 2 , 3 , 4 };
  int VertexCount=4;
  IndexedPointArray point = new IndexedPointArray(6,
  IndexedPointArray.COORDINATES|
  IndexedPointArray.COLOR_3,
  VertexCount);
  point.setCoordinates(0,vert);
  point.setColors(0,color);
  point.setCoordinateIndices(0,index);
  point.setColorIndices(0,index);
  PointAttributes pa = new PointAttributes();
  pa.setPointSize(20.0f);
  pa.setPointAntialiasingEnable(true);
  Appearance ap = new Appearance();
   ap.setPointAttributes(pa);
  this.setGeometry(point);
  this.setAppearance(ap);
  }
  }
  //end of pointShape.java
  --------------------------------------------
  //Point4.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Point4 extends Applet {
  private BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  Shape3D shape = new pointShape();
  objRoot.addChild(shape);
  objRoot.compile();
  return objRoot;
  }
  public Point4() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Point4(), 400,400);
  }
  }
  //end of Point4.java
  六. 能够旋转的点
  前面介绍的JAVA3D程序,显示的内容是静止的,且看不出立体的效果,为此,我们使
程序中的点绕着Y轴旋转,这样就可以看到具有立体效果的点了,当然,其它形体也可以按
同样的方法编程,程序调用了上面给出的pointShape.java。
  //Point5.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Point5 extends Applet {
  private BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  objRoot.addChild(createObject());
  objRoot.compile();
  return objRoot;
  }
  private Group createObject() {
  Transform3D t = new Transform3D();
  TransformGroup objTrans = new TransformGroup(t);
  objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  Shape3D shape = new pointShape();
  objTrans.addChild(shape);
  Transform3D yAxis = new Transform3D();
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, objTrans, yAxis,
   0.0f, (float) Math.PI*2.0f);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 50.0);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  return objTrans;
  }
  public Point5() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Point5(), 400,400);
  }
  }
  //end of Point5.java
  在Point4.java的objRoot里,放置的是一个Shape3D对象,而在Point5.java的objRoo
t里,放置的是一个Group对象。在生成对象的createObject() 方法里,为了使得形体能够
产生旋转运动,我们首先建立了一个TransformGroup对象和一个Transform3D对象,通过C
apability参数的设置,表示在程序运行时,objTrans能够进行几何变换,并将形体放入o
bjTrans。
  JAVA3D之所以能够使形体运动,是因为JAVA3D拥有类似于VRML的时间传感器节点的Al
pha对象,和类似于VRML的内插器节点的各种Interpolator对象,它们在由BoundingSpher
e等对象所设定的范围内在特定的时间内进行几何坐标变化,因而使形体产生运动变化的效
果。
  本程序中,Alpha给出了一个4秒钟的循环变化时间周期;RotationInterpolator规定
了形体每4秒钟绕着Y轴旋转一周。BoundingSphere表示所有距离坐标原点50米之内的
形体均可以旋转运动,而在这范围之外的所有形体均不产生运动。和Point5.java相类似的
VRML程序如下,VRML里的点不能够改变大小:
  //Point5.wrl
  #VRML V2.0 utf8
  DEF T Transform{
  childrenShape {
  geometry PointSet {
  coord Coordinate {
  point [.8 .8 .0, -.8, .8 0, .5 0 0,
  -.5 0 0, -.8 -.8 0, .8 -.8 0]}
  color Color{
  color [ .0 .5 1., .5 .0 1, 0 .8 .2,
  1 0 .3, 0 1 .3, .3 .8 0 ]}
   }}}
  DEF TS TimeSensor{
  cycleInterval 4
  loop TRUE}
  DEF OI OrientationInterpolator{
   key[0 .25 .5 .75 1]
   keyValue [0 1 0 1, 0 1 01.57,0 1 0 3.14
   0 1 0 4.71 0 1 06.28]}
  ROUTE TS.fraction TO OI.fraction
  ROUTE OI.value TO T.rotation
  # end of Point5.wrl
  JAVA3D学习系列(七)--线的生成
  BBS水木清华张杰
  我们可以利用JAVA3D的一些对象,生成各种直线。可以生成直线的对象有:
  1.LineArray
  LineArray(int vertexCount, int vertexFormat)
  2.LineStripArray
  LineStripArray(int vertexCount ,int vertexFormat,
   int[] stripVertexCounts )
  3.IndexedLineArray
  IndexedLineArray(int vertexCount, int vertexFormat,
   int indexCount )
  4.IndexedLineStripArray
  IndexedLineStripArray( int vertexCount, int vertexFormat,
   int indexCount, int stripIndexCounts[])
  一. 利用LineArray生成直线
  LineArray对象的定义如下:
  LineArray(int vertexCount, int vertexFormat)
  这里:
  vertexCount表示顶点的个数(必须为偶数)
  vertexFormat表示顶点的格式(第七讲有介绍)
  由下面的程序我们得知,Line1.java和前面介绍的Point4.java几乎完全一样,lineS
hape1.java和pointShape.java也相差不多。运行Line1.java我们获得了三条直线,由此得
知,LineArray的作用是生成多条直线,顶点坐标数组的每一对数据构成一条直线。
  在编写LineArray生成的直线时,要注重,顶点及颜色的个数必须相等且为偶数,此数
目必须赋值于vertexCount,也即程序中的vertexCount必须为偶数且不能少于顶点的个数

   --------------------------第一条
   ----------------第二条
   --------------------------第三条
  我们可以根据各种不同的情况,生成不同的直线,如给定宽度的直线、虚线等。相应
的的方法有:
  setLineWidth(float lineWidth)
  setLinePattern(int linePattern)
  setLineAntialiasingEnable(boolean state)
  对于线型linePattern有以下数据可选:
  intPATTERN_SOLID
  intPATTERN_DASH
  intPATTERN_DOT
  intPATTERN_DASH_DOT
  这些内容对所有种类的直线都有效。
  前面我们利用PointArray生成了六个点,这里,我们将前面的pointShape.java稍微变
化一下,则同样的六个点生成了三条直线,所用的两个程序为:
  //lineShape1.java
  import javax.media.j3d.*;
  public class lineShape1 extends Shape3D {
  private float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  public lineShape1() {
  LineArray line = new LineArray(6,
  LineArray.COORDINATES|LineArray.COLOR_3);
  line.setCoordinates(0,vert);
  line.setColors(0,color);
  LineAttributes la = new LineAttributes();
  la.setLineWidth(5.0f);
  la.setLineAntialiasingEnable(true);
  Appearance ap = new Appearance();
   ap.setLineAttributes(la);
  this.setGeometry(line);
  this.setAppearance(ap);
  }
  }
  //end of lineShape1.java
  ------------------------------------
  //Line1.java---using LineArray object
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Line1 extends Applet {
  private BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  Shape3D shape = new lineShape1();
  objRoot.addChild(shape);
  objRoot.compile();
  return objRoot;
  }
  public Line1() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Line1(), 400,400);
  }
  }
  //end of Line1.java
  二. 利用LineStripArray生成直线
  LineStripArray可用来生成多条折线段
  LineStripArray对象的定义如下:
  LineStripArray(int vertexCount ,int vertexFormat,
   int[] stripVertexCounts )
  这里:
  vertexCount表示顶点的个数(必须为偶数)
  vertexFormat表示顶点的格式(第七讲有介绍)
  stripVertexCounts为一数组,数组里的每一个数值表示
  每条折线段所拥有的顶点数目。
  下面我们利用lineShape1.java同样的顶点坐标数组及颜色数组,用LineStripArray对
象生成直线。程序也是两个:
  lineShape2.java、Line2.java,并使生成的直线绕着Y轴旋转,直线线型为虚线,线
宽为30个像素。
  //lineShape2.java
  import javax.media.j3d.*;
  public class lineShape2 extends Shape3D {
  int StripCount[] = new int[1];
  private float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  public lineShape2() {
  StripCount[0] = 6;
  LineStripArray line = new LineStripArray(6,
  LineStripArray.COORDINATES|
  LineStripArray.COLOR_3,StripCount);
  line.setCoordinates(0,vert);
  line.setColors(0,color);
  LineAttributes la = new LineAttributes();
  la.setLineWidth(30.0f);
  la.setLineAntialiasingEnable(true);
  la.setLinePattern(LineAttributes.PATTERN_DASH);
  Appearance ap = new Appearance();
  ap.setLineAttributes(la);
  this.setGeometry(line);
  this.setAppearance(ap);
  }
  }
  //end of lineShape2.java
  -----------------------------------------
  //Line2.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Line2 extends Applet {
  private BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  objRoot.addChild(createObject());
  objRoot.compile();
  return objRoot;
  }
  private Group createObject() {
  Transform3D t = new Transform3D();
  TransformGroup objTrans = new TransformGroup(t);
  objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  Shape3D shape = new lineShape2();
  objTrans.addChild(shape);
  Transform3D yAxis = new Transform3D();
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, objTrans, yAxis,
   0.0f, (float) Math.PI*2.0f);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 50.0);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  return objTrans;
  }
  public Line2() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Line2(), 400,400);
  }
  }
  //end of Line2.java
  由上可知,Line2.java这个程序和Point5.java几乎没有什么差别,除了类的名字于调
用的外部程序名不同之外,其余完全相同。
  lineShape1.java和lineShape2.java相差不大,lineShape2.java多了一个StripCoun
t数组,它可以用来生成多个折线段,下面的lineShape3.java程序就将Line2.java生成的
一条折线段分成了两条折线段:0、1、2三个点构成了一个折线段,3、4、5构成了另一条
折线段,每个折线段的顶点数目就构成了数组StripCount,StripCount数组的大小等于折
线段的数目。
  //lineShape3.java
  import javax.media.j3d.*;
  public class lineShape3 extends Shape3D {
  int StripCount[] = new int[2];
  private float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  public lineShape3() {
  StripCount[0] = 3;
  StripCount[1] = 3;
  LineStripArray line = new LineStripArray(6,
  LineStripArray.COORDINATES|
  LineStripArray.COLOR_3,StripCount);
  line.setCoordinates(0,vert);
  line.setColors(0,color);
  LineAttributes la = new LineAttributes();
  la.setLineWidth(30.0f);
  la.setLineAntialiasingEnable(true);
  la.setLinePattern(LineAttributes.PATTERN_DASH);
  Appearance ap = new Appearance();
   ap.setLineAttributes(la);
  this.setGeometry(line);
  this.setAppearance(ap);
  }
  }
  //end of lineShape3.java
  将lineShape3.java生成的绕Y轴旋转的形体用VRML程序表示的结果为:
  #VRML V2.0 utf8
  DEF T Transform{
  childrenShape {
  geometry IndexedLineSet {
  coord Coordinate {
  point [.8 .8 .0, -.8, .8 0, .5 0 0,
  -.5 0 0, -.8 -.8 0, .8 -.8 0]}
  coordIndex [0 1 2 -1, 3 4 5 ]
  #两个折线段
  color Color{
  color [ .0 .5 1., .5 .0 1, 0 .8 .2,
  1 0 .3, 0 1 .3, .3 .8 0 ]}
   }}}
  DEF TS TimeSensor{
  cycleInterval 4
  loop TRUE}
  DEF OI OrientationInterpolator{
   key[0 .25 .5 .75 1]
   keyValue [0 1 0 1, 0 1 01.57,0 1 0 3.14
   0 1 0 4.71 0 1 06.28]}
  ROUTE TS.fraction TO OI.fraction
  ROUTE OI.value TO T.rotation
  #end of lineShape3.wrl
  三. 利用IndexedLineArray生成直线
  IndexedLineArray对象的定义为:
  IndexedLineArray(int vertexCount, int vertexFormat,
  int indexCount )
  这里:
  vertexCount表示顶点数组里顶点的个数
  vertexFormat表示顶点的格式(第七讲有介绍)
  indexCount表示选用的顶点个数,假如一个点用了
  几次,则要把几次加进去
  在上一节里我们介绍了利用IndexedPoint生成点的程序,和IndexedPoint相类似,我
们可以利用IndexedLineArray生成直线段。
  下面的lineShape4.java利用了IndexedLineArray从六个点中挑选了3个点,生成了2条
直线。
  从程序中我们可以看到,下标为0的点使用了两次,但生成的是两条线,因而参数Ver
texCount应为4,即此处的VertexCount的数值应为直线条数的两倍。
  //lineShape4.java
  import javax.media.j3d.*;
  public class lineShape4 extends Shape3D {
  int[] index={ 1, 0, 0 , 3, };
  int VertexCount=4;
  private float vert[] = {
  .8f, 0.8f,0.0f,
  -0.8f, 0.8f,0.0f,
  0.5f, 0.0f,0.0f,
  -0.5f, 0.0f,0.0f,
  -0.8f,-0.8f,0.0f,
  0.8f,-0.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  };
  public lineShape4() {
  IndexedLineArray line = new IndexedLineArray(6,
  IndexedLineArray.COORDINATES|
  IndexedLineArray.COLOR_3,VertexCount);
  line.setCoordinates(0,vert);
  line.setColors(0,color);
  line.setCoordinateIndices(0,index);
  line.setColorIndices(0,index);
  LineAttributes la = new LineAttributes();
  la.setLineWidth(30.0f);
  la.setLineAntialiasingEnable(true);
  la.setLinePattern(LineAttributes.PATTERN_DASH);
  Appearance ap = new Appearance();
   ap.setLineAttributes(la);
  this.setGeometry(line);
  this.setAppearance(ap);
  }
  }
  //end of lineShape4.java
  将lineShape4.java翻译成VRML的相应程序为:
  #VRML V2.0 utf8
  DEF T Transform{
  childrenShape {
  geometry IndexedLineSet {
  coord Coordinate {
  point [.8 .8 .0, -.8, .8 0, .5 0 0,
  -.5 0 0, -.8 -.8 0, .8 -.8 0]}
  coordIndex [1 0 -1 0 3]
  color Color{
  color [ .0 .5 1., .5 .0 1, 0 .8 .2,
  1 0 .3, 0 1 .3, .3 .8 0 ]}
   }}}
  DEF TS TimeSensor{
  cycleInterval 4
  loop TRUE}
  DEF OI OrientationInterpolator{
   key[0 .25 .5 .75 1]
   keyValue [0 1 0 1, 0 1 01.57,0 1 0 3.14
   0 1 0 4.71 0 1 06.28]}
  ROUTE TS.fraction TO OI.fraction
  ROUTE OI.value TO T.rotation
  四. 利用IndexedLineStripArray生成直线
  IndexedLineStripArray对象的定义如下:
  IndexedLineStripArray( int vertexCount, int vertexFormat,
   int indexCount, int stripIndexCounts[])
  这里:
  vertexCount表示顶点数组里顶点的个数
  vertexFormat表示顶点的格式(第七讲有介绍)
  indexCount表示选用的顶点的个数
  stripIndexCounts为一数组,数组里的每一个数值表示每条折线段所拥有的顶点数目

  下面的程序里,我们给出10个顶点,
  --0----1--
  --2----3--
  --4----5--
  --6----7--
  --8----9--
  然后我们用IndexedLineStripArray生成三个折线段,第一个折线段为:0 1 3 2,第
二个折线段为3、5、4,第三个折线段为6、7、8、6,最后一个点没有用到。所有的直线宽
度为30像数。这时我们只用了10个点中的9个点,但有2个点用了两次,因而程序中的vert
exCount为11,程序如下:
  //lineShape5.java
  import javax.media.j3d.*;
  public class lineShape5 extends Shape3D {
  int StripCount[] = new int[3];
  int[] index={ 0 , 1 , 3 , 2 , 3 , 5 ,
  4 , 6 , 7 , 8 , 6 } ;
   int vertexCount = 11;
  private float vert[] = {
  -.3f , .8f , .0f,
   .3f , .8f , .0f,
  -.3f , .4f , .0f,
   .3f , .4f , .0f,
  -.3f , .0f , .0f,
   .3f , .0f , .0f,
  -.3f , -.4f , .0f,
   .3f , -.4f , .0f,
  -.3f , -.8f , .0f,
   .3f , -.8f , .0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f
  };
  public lineShape5() {
  StripCount[0] = 4;
  StripCount[1] = 3;
  StripCount[2] = 4;
  IndexedLineStripArray line = new IndexedLineStripArray(10 ,
  IndexedLineStripArray.COORDINATES|
  IndexedLineStripArray.COLOR_3, vertexCount , StripCount);
  line.setCoordinates(0,vert);
  line.setColors(0,color);
  line.setCoordinateIndices(0,index);
  line.setColorIndices(0,index);
  LineAttributes la = new LineAttributes();
  la.setLineWidth(30.0f);
  la.setLineAntialiasingEnable(true);
  la.setLinePattern(LineAttributes.PATTERN_DASH);
  Appearance ap = new Appearance();
   ap.setLineAttributes(la);
  this.setGeometry(line);
  this.setAppearance(ap);
  }
  }
  //end of lineShape5.java

JAVA3D学习系列(八)--面的生成(上)
BBS水木清华 张杰

  一. 生成平面的对象及其定义
  JAVA3D可通过编程显示出面来,面有两种:三角形和四边形,相应的对象为Triangle
和Quad。
  JAVA3D用于生成平面的对象有:
  1.TriangleArray
  TriangleArray (int vertexCount, int vertexFormat )
  2.QuadArray
  QuadArray (int vertexCount, int vertexFormat )
  3.TriangleStripArray
  TriangleStripArray ( int vertexCount , int vertexFormat,
   int[] stripVertexCounts )
  4.TriangleFanArray
  TriangleFanArray ( int vertexCount ,int vetexFormat,
   int[] stripVertexCounts )
  5.IndexedTriangleArray
  IndexedTriangleArray (int vertexCount , int vertexFormat,
  int indexCount)
  6.IndexedQuadArray
  IndexedQuadArray (int vertexCount , int vertexFormat,
  int indexCount )
  7.IndexedTriangleStripArray
  IndexedTriangleStripArray( int vertexCount, int vertexFormat,
   int indexCount, int stripIndexCounts[])
  8.IndexedTriangleFanArray
  IndexedTriangleFanArray ( int vertexCount, int vertexFormat,
  int indexCount, int stripIndexCounts[])
  二. TriangleArray生成的面
  和前面介绍的PointArray、LineArray一样,面也可以用
  TriangleArray来生成,利用它可以生成三角片面我们先看一下TriangleArray的定义

  TriangleArray (int vertexCount, int vertexFormat )
  这里:
  vertexCount表示顶点的个数(必须为三的倍数)
  vertexFormat表示顶点的格式(第七讲有介绍)
  下面我们看一个利用TriangleArray的例子,例子里有九个点。
  --1-- --4----7--
   --0----3----6--
  --2-- --5----8--
  //triShape1.java
  import javax.media.j3d.*;
  public class triShape1 extends Shape3D {
  private float vert[] = {
  -.8f , .0f ,0.0f,
  -.4f , .8f ,0.0f,
  -.4f , -.8f,0.0f,
  -.2f , .0f ,0.0f,
  0.2f , .8f ,0.0f,
  0.2f , -.8f,0.0f,
  0.4f , .0f ,0.0f,
  0.8f , .8f ,0.0f,
  0.8f , -.8f,0.0f,
   };
  private float color[] = {
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,
  1.0f,0.0f,0.3f,
  0.0f,1.0f,0.3f,
  0.3f,0.8f,0.0f,
  0.0f,0.5f,1.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.8f,2.0f,e3D {
  int StripCount[] = new int[2];
   private float vert[] = {
   -.6f ,.8f , 0.0f,
   -.6f , -.8f,0.2f,
  -0.2f ,.5f,-.2f,
  -0.2f , -.5f , 0.2f,
   0.0f , -.5f,-.2f,
   0.0f ,.5f ,.2f,
   0.2f ,.0f, .0f,
   0.2f ,.8f , 0.3f,
   0.2f , -.8f, -0.3f,
   0.6f ,.8f,0.0f,
   0.6f , -.8f,0.5f,
   0.8f , 0.0f ,.3f
   };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  5.0f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  };
  public triShape3() {
  StripCount[0] = 7;
  StripCount[1] = 5;
  TriangleStripArray tri = new TriangleStripArray(12,
   TriangleStripArray.COORDINATES|
  TriangleStripArray.COLOR_3 , StripCount);
  tri.setCoordinates(0,vert);
  tri.setColors(0,color);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(tri);
  this.setAppearance(ap);
  this.setGeometry(tri);
   }
  }
  //end of triShape3.java
  五. TriangleFanArray生成的面
  TriangleFanArray对象的定义为:
  TriangleFanArray ( int vertexCount ,int vetexFormat,
   int[] stripVertexCounts )
  利用TriangleFanArray对象,我们可以生成多组三角片面,每组三角片面占用一定数
量的顶点,每个组在生成三角片面时,头三个顶点构成一个三角片面,其余的顶点和前面
的顶点及每组第一个顶点生成一个三角片面。下面的triShape4.java程序中,我们生成了
两组三角片面,头5个点生成了三个相连的三角片面,后6个点生成了四个相连的三角片面
。外形就像两把扇子,一大一小。
  //triShape4.java
  import javax.media.j3d.*;
  public class triShape4 extends Shape3D {
  int FanCount[] = new int[2];
   private float vert[] = {
  0.0f , 0.0f , 0.0f,
  -0.3f , 0.3f , 0.02f,
  -0.1f , 0.4f , -0.02f,
   0.1f , 0.4f ,0.02f,
   0.3f,0.3f ,-0.02f,
   0.0f, -0.8f ,0.0f,
  -0.6f, -0.2f,0.02f,
  -0.3f, -0.1f , -0.02f,
   .0f, -0.05f, 0.02f,
   .3f, -0.1f, -0.02f,
   .6f, -0.2f,0.02f
  };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  5.0f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
   1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  };
  public triShape4() {
  FanCount[0] = 5;
  FanCount[1] = 6;
  TriangleFanArray tri = new TriangleFanArray(11,
   TriangleFanArray.COORDINATES|
  TriangleFanArray.COLOR_3 , FanCount);
  tri.setCoordinates(0,vert);
  tri.setColors(0,color);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(tri);
  this.setAppearance(ap);
  this.setGeometry(tri);
   }
  }
  //end of triShape4.java
  JAVA3D学习系列(八)--面的生成(下)
  BBS水木清华张杰
  一. IndexedTriangleArray生成的面
  IndexedTriangleArray对象的定义为:
  IndexedTriangleArray (int vertexCount , int vertexFormat,
  int indexCount)
  利用这个对象,我们可以从一个顶点数组中挑选一些顶点生成自己所需要的三角片面
。程序triShape5.java中,有一个10个点的数组,我们从这个数组中选择了8个点,生成了
三个面,其中有一个点用了两次,假如所挑选的点都只用一次,则选择的点的数目必须为
3的倍数。
  另外,在编程时,我们要注重点的旋转顺序,逆时针旋转和顺时针旋转有时会产生不
同的效果。
  程序中,vertexCount表示顶点数组顶点的总数,indexCount表示生成的面的顶点个数
,数值为面的个数的三倍,本例中,生成的面为三个,故vertexCount为9。
  //triShape5.java
  import javax.media.j3d.*;
  public class triShape5 extends Shape3D {
   private float vert[] = {
   -.6f ,.6f ,.0f ,
   -.6f , -.6f, .0f ,
   -.3f ,.6f ,.0f ,
   -.3f , -.6f, .0f ,
   -.0f ,.6f ,.0f ,
   -.0f , -.6f, .0f ,
  .3f ,.6f ,.0f ,
  .3f , -.6f, .0f ,
  .6f ,.6f ,.0f ,
  .6f , -.6f, .0f ,
  };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  5.0f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
   1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  };
  public triShape5() {
   int[] index={ 0 , 1 ,2 , 4 , 5 , 6 , 6 , 7 , 8 };
  int VertexCount=9;
  IndexedTriangleArray tri = new IndexedTriangleArray(10,
   IndexedTriangleArray.COORDINATES|
  IndexedTriangleArray.COLOR_3 , VertexCount);
  tri.setCoordinates(0,vert);
  tri.setColors(0,color);
  tri.setCoordinateIndices(0,index);
  tri.setColorIndices(0,index);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(tri);
  this.setAppearance(ap);
  this.setGeometry(tri);
   }
  }
  //end of triShape5.java
  二. IndexedQuadArray生成的面
  IndexedQuadArray对象的定义为:
  IndexedQuadArray (int vertexCount , int vertexFormat,
  int indexCount )
  利用这个对象,我们可以从一个顶点数组中挑选一些顶点生成自己所需要的四个点所
构成的平面。程序quadShape2.java中,有一个10个点的数组,我们从这个数组中选择了7
个点,生成了两个面,其中有一个点用了两次,假如所挑选的点都只用一次,则选择的点
的数目必须为4的倍数。这些选中的点构成了数组index。在输入每一个顶点的坐标及颜色
时,我们用到了下面两种方法:
  setCoordinateIndices(0,index);
  setColorIndices(0,index);
  程序中,vertexCount表示顶点数组顶点的总数,indexCount表示生成的面的顶点个数
,数值为面的个数的4倍,本例中,生成的面为两个,故vertexCount为8。
  编写IndexedQuadArray应用程序时,我们仍然要注重下面几个问题。
  首先是四点应当共面,假如不共面,程序仍然可以编译运行,但显示的内容为两个三
角面。
  其次是四个点组成的面不应有凹点,这有点象VRML程序中的Extrusion、IndexedFace
Set里的情况,当然,在VRML程序中四个点构成的面可以有凹点,这时只需要在相应的节点
内加上一个参数:
  convexTRUE
  而在JAVA3D程序中,假如QuadArray生成的面有凹点时,程序的显示结果会不正确。

  //quadShape2.java
  import javax.media.j3d.*;
  public class quadShape2 extends Shape3D {
   private float vert[] = {
   -.6f , .6f , .0f ,
   -.6f , -.6f, .0f ,
   -.3f , .6f , .0f ,
   -.3f , -.6f, .0f ,
   -.0f , .6f , .0f ,
   -.0f , -.6f, .0f ,
   .3f , .6f , .0f ,
   .3f , -.6f, .0f ,
   .6f , .6f , .0f ,
   .6f , -.6f, .0f ,
  };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  5.0f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
   1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  };
  public quadShape2() {
   int[] index={ 2 , 1 , 3 , 4 , 4 , 7 , 9 , 6};
  int VertexCount=8;
  IndexedQuadArray quad = new IndexedQuadArray(10,
   IndexedQuadArray.COORDINATES|
  IndexedQuadArray.COLOR_3 , VertexCount);
  quad.setCoordinates(0,vert);
  quad.setColors(0,color);
  quad.setCoordinateIndices(0,index);
  quad.setColorIndices(0,index);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(quad);
  this.setAppearance(ap);
  this.setGeometry(quad);
   }
  }
  //end of quadShape2.java
  三. IndexedTriangleStripArray生成的面
  IndexedTriangleStripArray对象的定义为:
  IndexedTriangleStripArray( int vertexCount, int vertexFormat,
   int indexCount, int stripIndexCounts[])
  利用IndexedTriangleStripArray对象,我们可以生成多组三角片面,对于每一组三角
片面来说,它的头三个点生成一个面,从第四个点开始,每一个点都和前两个点生成一个
新的面。这些点可以通过一个数组index从一个顶点数组中任意选取,它和TriangleStrip
Array的差别在于TriangleStripArray对顶点没有选择权,而IndexedTriangleStripArray
对顶点具有选择权,其它的都一样。
  程序triShape6.java给出了一个16个数构成的顶点数组,从中挑选了两组数,每一组
都有6个顶点构成并生成了相连的四个三角片面。
  //triShape6.java
  import javax.media.j3d.*;
  public class triShape6 extends Shape3D {
   int StripCount[] = new int[2];
   private float vert[] = {
  -.6f ,.6f ,.1f ,
  -.6f ,.2f ,.2f ,
  -.6f , -.2f ,.1f ,
  -.6f , -.6f ,.2f ,
  -.0f ,.6f , -.1f ,
  -.0f ,.2f , -.2f ,
  -.0f , -.2f , -.1f ,
  -.0f , -.6f , -.2f ,
   .6f ,.6f ,.1f ,
   .6f ,.2f ,.2f ,
   .6f , -.2f ,.1f ,
   .6f , -.6f ,.2f ,
  };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  5.0f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  };
  public triShape6() {
   int[] index={ 0 , 1 , 4 , 5 , 8 , 9 , 2 , 3 , 6 , 7 , 10};
   StripCount[0] = 6;
  StripCount[1] = 5;
  int indexCount=11;
  IndexedTriangleStripArray tri = new IndexedTriangleStripArray(12,
   IndexedTriangleStripArray.COORDINATES|
  IndexedTriangleStripArray.COLOR_3 , indexCount , StripCount);
  tri.setCoordinates(0,vert);
  tri.setColors(0,color);
  tri.setCoordinateIndices(0,index);
  tri.setColorIndices(0,index);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(tri);
  this.setAppearance(ap);
  this.setGeometry(tri);
   }
  }
  //end of Shape6.java
  四. IndexedTriangleFanArray生成的面
  IndexedTriangleFanArray对象的定义为:
  IndexedTriangleFanArray ( int vertexCount, int vertexFormat,
  int indexCount, int stripIndexCounts[])
  利用这一对象,我们可以从一组顶点数组中挑选我们所需要的顶点,生成多组三角片
面,每组三角片面占用一定数量的顶点,每个组在生成三角片面时,头三个顶点构成一个
三角片面,其余的顶点和前面的顶点及每组第一个顶点生成一个三角片面。下面的triSha
pe7.java程序中,我们生成了两组三角片面,头5个点生成了三个相连的三角片面,后6个
点生成了四个相连的三角片面。外形就像两把扇子,一大一小。程序中所用的数组为20个
点的顶点数组。
  IndexedTriangleFanArray对象和TriangleFanArray的应用方法很相似,它们之间的不
同在于IndexedTriangleFanArray对象可以从顶点数组中挑选自己所需要的顶点,而Trian
gleFanArray对象没有挑选权,只能被动地使用顶点数组中的数据。
  //triShape7.java
  import javax.media.j3d.*;
  public class triShape7 extends Shape3D {
   int StripCount[] = new int[2];
   private float vert[] = {
  -.6f , .8f , -.1f ,
  -.6f , .4f , -.0f ,
  -.6f , .0f ,.1f ,
  -.6f , -.8f , -.1f ,
  -.4f , .8f , .1f ,
  -.4f , .4f , .1f ,
  -.4f , .0f ,-.1f ,
  -.4f , -.8f , .1f ,
  -.0f , .8f , -.1f ,
  -.0f , .4f , -.0f ,
  -.0f , .0f ,.1f ,
  -.0f , -.8f , -.1f ,
  .4f , .8f , .1f ,
  .4f , .4f , -.05f ,
  .4f , .0f ,-.1f ,
  .4f , -.8f , .1f ,
   .6f , .8f , -.1f ,
   .6f , .4f , -.0f ,
   .6f , .0f ,.1f ,
   .6f , -.8f , -.1f ,
  };
  private float color[] = {
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  1.0f,0.8f,0.0f,
  0.5f,1.0f,0.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,1.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  0.0f,0.5f,1.0f,
  1.0f,0.5f,0.0f,
  1.0f,0.0f,0.5f,
  0.9f,1.0f,0.0f,
  0.5f,0.0f,1.0f,
  };
  public triShape7() {
   int[] index={ 9 , 4 , 8 , 12 , 16 , 11 , 2 , 6 , 10 , 14 , 18};
   StripCount[0] = 5;
  StripCount[1] = 6;
  int indexCount=11;
  IndexedTriangleFanArray tri = new IndexedTriangleFanArray(20,
   IndexedTriangleFanArray.COORDINATES|
  IndexedTriangleFanArray.COLOR_3 , indexCount , StripCount);
  tri.setCoordinates(0,vert);
  tri.setColors(0,color);
  tri.setCoordinateIndices(0,index);
  tri.setColorIndices(0,index);
  PolygonAttributes pa = new PolygonAttributes();
  pa.setCullFace(PolygonAttributes.CULL_NONE);
  Appearance ap = new Appearance();
  ap.setPolygonAttributes(pa);
  this.setGeometry(tri);
  this.setAppearance(ap);
  this.setGeometry(tri);
   }
  }
  /end of triShape7.java
  JAVA3D学习系列(九)---外部复杂形体的调用
  张 杰
  (Wavefront的OBJ,Lightwave的LWS和LWO,WRL,DWG,3DS)
  我们可以利用前面介绍的方法生成我们所需要的基本形体,生成点、线、平面。但有
的时候,我们需要用到其它格式的三维形体,如VRML2.0格式的图形文件,AUTOCAD绘出的
DWG格式的三维形体,3DS MAX绘制出的复杂形体。对于这些形体,我们可以非常方便地将
其用到JAVA3D程序中去。下面我们介绍一些图形格式在JAVA3D中的应用方法。
  一. Wavefront的OBJ格式的图形文件的调用
  1. OBJ格式图形的简单调用
  JAVA3D编译环境所带的UTILITY有两个LOADER,一个可用来调用Wavefront软件的OBJ格
式的三维图形格式文件,一个可用来调用Lightwave软件的LWS及LWO格式的三维图形格式文
件。
  假设我们有一个OBJ格式的文件(JAVA3D附带有两个OBJ,文件名分别为galleon.obj和
p51_mustang.obj,以及调用它们的一个程序ObjLoad.java)。
  我们编写的第一个程序Obj1.java介绍了OBJ图形的调用方法。
  程序的便宜方法:
  javac Obj1.java
  程序的运行方法(假设图形在同一目录):
  java Obj1 galleon.obj
  //Obj1.java
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  import com.sun.j3d.loaders.ParsingErrorException;
  import com.sun.j3d.loaders.IncorrectFormatException;
  import com.sun.j3d.loaders.Scene;
  import java.io.*;
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Obj1 extends Applet {
  private String filename = null;
  public BranchGroup createSceneGraph(String args[]){
  BranchGroup objRoot = new BranchGroup();
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  BoundingSphere bounds =
  new BoundingSphere(ne罚?颐歉?隽耍?nbsp;
  private double creaseAngle = 60.0;
  ------------------------------------------------
  易都站注:上面的程序原文如此,肯定是出现了异常。作为弥补,下面我把以前从张
杰网站上收集来的二个相关的程序贴出来,供感爱好的网友参考:
  //Obj1.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  import com.sun.j3d.loaders.Scene;
  import com.sun.j3d.loaders.objectfile.ObjectFile;

  public class Obj1 extends Applet {
   public BranchGroup createSceneGraph() {
    BranchGroup objRoot = new BranchGroup();
    TransformGroup objScale = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(0.8);
    objScale.setTransform(t3d);
    objRoot.addChild(objScale);

    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 1
00.0);

    Color3f lightColor = new Color3f(1.0f, 1.0f, 0.9f);
    Vector3f lightDirection = new Vector3f(4.0f, -7.0f, -12.0f);
    DirectionalLight light = new DirectionalLight(lightColor, lightDirecti
on);
    light.setInfluencingBounds(bounds);
    objRoot.addChild(light);

    TransformGroup objTrans = new TransformGroup();
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objScale.addChild(objTrans);

    BranchGroup b = new objLoad("galleon.obj");
    objTrans.addChild(b);

    Transform3D yAxis = new Transform3D();
    Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
     0, 0, 4000, 0, 0, 0, 0, 0);
    RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,

     objTrans, yAxis, 0.0f, (float) Math.PI*2.0f);

    rotator.setSchedulingBounds(bounds);
    objTrans.addChild(rotator);
    objRoot.compile();
    return objRoot;
   }

   public Obj1(String args[]) {
    setLayout(new BorderLayout());
    Canvas3D c = new Canvas3D(null);
    add("Center", c);
    BranchGroup scene = createSceneGraph();
    SimpleUniverse u = new SimpleUniverse(c);
    u.getViewingPlatform().setNominalViewingTransform();
    u.addBranchGraph(scene);
   }

   public static void main(String[] args) {
    new MainFrame(new Obj1(args), 400,400);
   }
  }
  //end of Obj1.java

  //objLoad.java
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  import com.sun.j3d.loaders.ParsingErrorException;
  import com.sun.j3d.loaders.IncorrectFormatException;
  import com.sun.j3d.loaders.Scene;
  import java.io.*;
  import javax.media.j3d.*;

  public class objLoad extends BranchGroup{
   public objLoad(String filename) {
    BranchGroup obj = new BranchGroup( );
    int flags = ObjectFile.RESIZE;
    ObjectFile f = new ObjectFile(flags);
    Scene s = null;
    try {
     s = f.load(filename);
    }
    catch (FileNotFoundException e) {
     System.err.println(e);
     System.exit(1);
    }
    catch (ParsingErrorException e) {
     System.err.println(e);
     System.exit(1);
    }
    catch (IncorrectFormatException e) {
     System.err.println(e);
     System.exit(1);
    }
    obj.addChild(s.getSceneGroup());
    this.addChild(obj);
   }
  }
  //end of objLoad.java
  ------------------------------------------------
  它可以使程序运行时通过设定和VRML程序中同样的creaseAngle来提高或降低图形的显
示效果。给出了creaseAngle,f的定义也相应地有了变化,即调用的是ObjectFile的另一
个构造函数:
  ObjectFile f = new ObjectFile(flags,(float)(creaseAngle * Math.PI / 180.0)
);
并在前面定义了flag:
  int flags = ObjectFile.RESIZE;
  本人未获得定义ObjectFile对象的源程序,故猜测ObjectFile.RESIZE可能是一个开关
参数,表示答应改变尺寸。
  3.分成两个程序
  上面给出的两个程序,程序不是很清楚,阅读起来比较困难,为此,我们将Obj2.jav
a分解成两个程序:
  Obj3.java和objFile.java。
  //Obj3.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  import com.sun.j3d.loaders.Scene;
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  public class Obj3 extends Applet {
  public BranchGroup createSceneGraph(){
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objScale = new TransformGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.3);
  objScale.setTransform(t3d);
  objRoot.addChild(objScale);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
  Background bg = new Background(bgColor);
  bg.setApplicationBounds(bounds);
  objRoot.addChild(bg);
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
  TransformGroup objTrans = new TransformGroup();
  objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  objScale.addChild(objTrans);
  BranchGroup b1 = newobjFile("galleon.obj");
  objTrans.addChild(b1);
  Transform3D yAxis = new Transform3D();
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, objTrans, yAxis,
   0.0f, (float) Math.PI*2.0f);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  objRoot.compile();
  return objRoot;
  }
  public Obj3(String args[]) {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Obj3(args), 400,400);
  }
  }
  //end of Obj3.java
  --------------------------
  //objFile.java
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  import com.sun.j3d.loaders.ParsingErrorException;
  import com.sun.j3d.loaders.IncorrectFormatException;
  import com.sun.j3d.loaders.Scene;
  import java.io.*;
  import javax.media.j3d.*;
  public class objFile extends BranchGroup{
  private double creaseAngle = 60.0;
  publicobjFile(String filename){
  BranchGroup obj = new BranchGroup( );
  int flags = ObjectFile.RESIZE;
  ObjectFile f = new ObjectFile(flags,
  (float)(creaseAngle * Math.PI / 180.0));
  Scene s = null;
  try {
  s = f.load(filename);
  }
  catch (FileNotFoundException e) {
  System.err.println(e);
  System.exit(1);
  }
  catch (ParsingErrorException e) {
  System.err.println(e);
  System.exit(1);
  }
  catch (IncorrectFormatException e) {
  System.err.println(e);
  System.exit(1);
  }
  obj.addChild(s.getSceneGroup( ) );
   this.addChild(obj);
   }
  }
  //end of objFile.java
  4.同时调用两个形体,两者单独旋转。
  前面的程序中,形体只有一个,为此,我们编了一个程序,利用它可以调用两个OBJ形
体,一左一右,它们分别绕自身的轴旋转,当然,形体的生成仍然使用上面的objFile.ja
va程序。另外,我们还在程序中加了红色的背景。
  //Obj4.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  import com.sun.j3d.loaders.Scene;
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  public class Obj4 extends Applet {
  public BranchGroup createSceneGraph(){
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objScale = new TransformGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.3);
  objScale.setTransform(t3d);
  objRoot.addChild(objScale);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  Color3f bgColor = new Color3f(1.05f, 0.00f, 0.0f);
  Background bg = new Background(bgColor);
  bg.setApplicationBounds(bounds);
  objRoot.addChild(bg);
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
  BranchGroup b1 = newobjFile("1.obj");
  BranchGroup b2 = newobjFile("2.obj");
   objScale.addChild(createObject (b1, -1.2f , 0.0f ));
   objScale.addChild(createObject (b2, 1.2f , 0.0f ));
   objRoot.compile();
  return objRoot;
  }
  private GroupcreateObject (BranchGroup b, float xpos, float ypos ) {
  Transform3Dt = newTransform3D ( );
  t.setTranslation ( new Vector3f ( xpos, ypos, 0.0f ) );
  TransformGroup objTrans = new TransformGroup(t);
  TransformGroup spin = new TransformGroup();
  spin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  spin.addChild(b);
  Transform3DyAxis = newTransform3D ( );
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, spin, yAxis,
   0.0f, (float) Math.PI*2.0f);
   BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  objTrans.addChild ( spin );
   return objTrans ;
  }
  public Obj4(String args[]) {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Obj4(args), 400,400);
  }
  }
  //end of Obj4.java
  JAVA3D学习系列(十)---DWG、WRL及3DS MAX图形的调用
  BBS水木清华张杰
  一. VRML2.0(VRML97)图形文件在JAVA3D中的应用简介
  SUN公司为我们提供了一个VRML97的LOADER,利用它我们可以在JAVA3D程序中方便地调
用VRML图形。不过由于这个LOADER目前还不是很完善,因而没有放入JAVA3D之中,不过随
着它的完善,最终它会成为JAVA3D的一个组成部分,调用VRML97程序就象调用Wavefront的
OBJ一样简单。
  我们可以从以下的网址下载(VRML97.ZIP)并安装,下载的网址为:
 http://www.vrml.org/WorkingGroups/vrml-java3d/从这个网页上我们需要下载目前
大小为283KB的一个ZIP文件,VRML97.ZIP,利用解压程序将其解成VRML97.JAR,大小目前
为310KB,版本为0.90.2版,利用它可以让我们在JAVA3D程序中调用VRML97(VRML2.0)图
形。
  二. VRML97.JAR的安装
  获得VRML97.JAR后,假设我们的JDK1.2摆放的位置为目录JDK1.2,我们应将其放在下
面的子目录中:
   C:\jdk1.2\lib
  并在WINDOWS的AUTOEXEC.BAT文件中写入下面一行:
  SET CLASSPATH=%CLASSPATH%;C:\JDK1.2\LIB\vrml97.jar
  重新启动计算机,这样我们就可以利用它了。
  当然,我们可以将VRML97.JAR放在一个目录中,利用下面的方法将其解开,不过所获
得的全为CLASS文件。
  三. VRML97.JAR的应用
  1.利用VRML971.JAR调用一个VRML文件,使VRML文件中的形体不停地
  旋转,程序如下。
  程序的编译方法:
  javac Vrml1.java
  程序的运行方法(假设图形在同一目录):
  java Vrml1myShape.wrl
  当然,假如所调用的形体非常大或非常小时,需要修改:
  t3d.setScale(0.3);
  中的数值。
  //Vrml.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  import com.sun.j3d.loaders.vrml97.VrmlLoader;
  import com.sun.j3d.loaders.Scene;
  public class Vrml1 extends Applet {
  private String filename = null;
  public BranchGroup createSceneGraph(String args[]){
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objScale = new TransformGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.3);
  objScale.setTransform(t3d);
  objRoot.addChild(objScale);
   Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
  TransformGroup objTrans = new TransformGroup();
  objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  objScale.addChild(objTrans);
  VrmlLoader loader = new VrmlLoader();
  Scene s = null;
  try {
  s = loader.load(filename);
  } catch (Exception e) {
  System.err.println(e);
  System.exit(1);
  }
  objTrans.addChild(s.getSceneGroup());
  Transform3D yAxis = new Transform3D();
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, objTrans, yAxis,
   0.0f, (float) Math.PI*2.0f);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  objRoot.compile();
  return objRoot;
  }
  public Vrml1(String args[]) {
  filename = args[0];
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph(args);
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Vrml1(args), 400,400);
  }
  }
  //end of Vrml.java
  可以看出,Vrml1.java和前面介绍的Obj2.java非常相似。
  2.将Vrml.java分解成两个程序
  上面的程序中,用于处理调用问题的部分我们可以提取出来,这样我们就可以多次重
复使用。
  从下面的程序我们可以得知,Vrml2.java和前面介绍的Obj3.java除了Obj3改为Vrml2
,objFile改为vrmlLoad之外,其余什么也没有改变。vrmlLoad.java和objFile.java也非
常相似。
  //Vrml2.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  import com.sun.j3d.loaders.Scene;
  import com.sun.j3d.loaders.objectfile.ObjectFile;
  public class Vrml2 extends Applet {
  public BranchGroup createSceneGraph(){
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objScale = new TransformGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.3);
  objScale.setTransform(t3d);
  objRoot.addChild(objScale);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
  Background bg = new Background(bgColor);
  bg.setApplicationBounds(bounds);
  objRoot.addChild(bg);
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
  TransformGroup objTrans = new TransformGroup();
  objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  objScale.addChild(objTrans);
  BranchGroup b1 = newvrmlLoad("7.wrl");
  objTrans.addChild(b1);
  Transform3D yAxis = new Transform3D();
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, objTrans, yAxis,
   0.0f, (float) Math.PI*2.0f);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  objRoot.compile();
  return objRoot;
  }
  public Vrml2(String args[]) {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Vrml2(args), 400,400);
  }
  }
  //end of Vrml2.java
  -----------------------------
  //vrmlLoad.java
  import javax.media.j3d.*;
  import java.io.*;
  import com.sun.j3d.loaders.vrml97.VrmlLoader;
  import com.sun.j3d.loaders.Scene;
  public class vrmlLoad extends BranchGroup{
   publicvrmlLoad(String filename){
  BranchGroup obj = new BranchGroup( );
   VrmlLoader loader = new VrmlLoader();
  Scene s = null;
  try {
  s = loader.load(filename);
  } catch (Exception e) {
  System.err.println(e);
  System.exit(1);
  }
  obj.addChild(s.getSceneGroup( ) );
  this.addChild(obj);
   }
  }
  //end of vrmlLoad.java
  3.调用两个VRML文件并使其放在不同的位置处旋转,编写这个程序非常简单,只需将
前面介绍的Obj4.java稍作修改即可,程序如下:
  //Vrml3.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Vrml3 extends Applet {
  public BranchGroup createSceneGraph(){
  BranchGroup objRoot = new BranchGroup();
  TransformGroup objScale = new TransformGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.1);
  objScale.setTransform(t3d);
  objRoot.addChild(objScale);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
   Color3f bgColor = new Color3f(1.05f, 0.00f, 0.0f);
  Background bg = new Background(bgColor);
  bg.setApplicationBounds(bounds);
  objRoot.addChild(bg);
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
   BranchGroup b1 = newvrmlLoad("7.wrl");
  BranchGroup b2 = newvrmlLoad("8.wrl");
   objScale.addChild(createObject (b1, -1.2f , 0.0f ));
   objScale.addChild(createObject (b2, 1.2f , 0.0f ));
   objRoot.compile();
  return objRoot;
  }
  private GroupcreateObject (BranchGroup b, float xpos, float ypos ) {
   Transform3Dt = newTransform3D ( );
   t.setTranslation ( new Vector3f ( xpos, ypos, 0.0f ) );
  TransformGroup objTrans = new TransformGroup(t);
  TransformGroup spin = new TransformGroup();
  spin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  spin.addChild(b);
  Transform3DyAxis = newTransform3D ( );
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, spin, yAxis,
   0.0f, (float) Math.PI*2.0f);
   BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  rotator.setSchedulingBounds(bounds);
  objTrans.addChild(rotator);
  objTrans.addChild ( spin );
   return objTrans ;
  }
  public Vrml3(String args[]) {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Vrml3(args), 400,400);
  }
  }
  //end of Vrml3.java
  四. AUTOCAD R14的DWG图形及3DS MAX图形在JAVA3D中的应用。
  在三维图形生成过程中,国内目前大量使用AUTOCAD及3DS MAX等软件。如何将这些软
件生成的三维图形应用到JAVA3D上去呢?
  对于3DS MAX软件,处理起来非常方便,因为3DS MAX可以将其图形直接输出成VRML97
格式,因而可以按本讲介绍的方法处理。
  对于AUTOCAD R14来说,目前还不太方便,不知AUTOCAD 2000是否能直接输出VRML97图
形格式。本人从欧洲捷克一个站点拷得一个文件,可用来直接将AUTOCAD R14所绘制的三维
图形转换成VRML97(VRML2.0)格式,因而AUTOCAD软件生成的图形也可以非常方便地应用
到JAVA3D上面,为我们编写JAVA3D的复杂应用程序打下了良好的基础。此软件非常好用(
采用ARX技术编写)。
  JAVA3D学习系列(十一)--形体的组合及几何坐标变换
  BBS水木清华张杰
  JAVA3D学习系列(13)---形体的组合及几何坐标变换
  汕头大学机电系张杰(jzhang@mailserv.stu.edu.cn)
  ****************书名VRML2.0交互式三维图形编程******
  JAVA3D学习系列中的例题将有非常多的VRML程序与之相比较,介绍JAVA3D的顺序也和
VRML2.0新书基本一致,欢迎购买VRML2.0新书。
  非凡购书方式:
  1。作者售书
  1。网上订购(email address: jzhang@mailserv.stu.edu.cn)
  2。可以先获书,后汇款(不满足可退书),
   只需将通信地址及邮编告知作者,即可在最短的时间内得到书。
  3。书价为25元/本,免收邮购费用。
  4。书为16开本,正文161页。
  5. 购书可获盖有出版社财务章的收据。
  6. 假如需要书中所有的源程序,我可以email一个打包程序
  *************书名VRML2.0交互式三维图形编程******
  VRML2.0(VRML97)中,有两个用来组合各形体的组节点:
  Transform、Group,其中的Group节点完全可以用Transform节点来代替。如何在JAVA
3D中实现Transform所提供的几何变换功能,是我们把握JAVA3D应用编程的基础。下面我们
对此给以具体的介绍。
  我们首先来看一下VRML97的Transform节点的定义:
  Transform节点的定义是:
  Transform {
  eventIn MFNodeaddChildren
  eventIn MFNoderemoveChildren
  exposedFieldSFVec3f center 0 0 0
  exposedFieldMFNodechildren []
  exposedFieldSFRotationrotation 0 0 10
  exposedFieldSFVec3f scale1 1 1
  exposedFieldSFRotation scaleOrientation0 0 10
  exposedFieldSFVec3f translation0 0 0
  field SFVec3f bboxCenter 0 0 0
  field SFVec3f bboxSize -1 -1 -1
  }
  由定义我们可以看出,VRML程序中,我们可以通过设定translation、rotation、sca
le来使形体产生平移、旋转、比例变换。如VRML2.0交互式三维图形编程一书所给出的一个
生成一个小丑的程序Ex4_03.wrl,里面就对形体进行了平移、旋转、比例变换。我们先给
出Ex4_03.wrl程序(我们对书中的程序进行了修改,使生成的小丑能够旋转),再给出用
JAVA3D编写出来的Ex4_03.java。
  //Ex4_03.wrl
  #VRML V2.0 utf8
  DEF T Transform{
  children[
  Transform {
  scale 1 1.2 1
  children Shape {
  appearance Appearance{material Material
   {diffuseColor 1 1 0 }}
  geometry Sphere{}}}
  Transform{
  translation .5 .4 .6
  scale 1 1 2
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 0 0 1}}
  geometry Sphere{radius .2}}}
  Transform {
  translation -.5 .4 .6
  scale 1 1 2
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 0 0 1}}
  geometry Sphere {radius .2}}}
  Transform{
  translation 0 1 0
  scale 1.1 .4 1.1
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 1 0 0}}
  geometry Cone{}}}
  Transform{
  translation 1 0 0
  scale .2 .4 .2
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 0 1 1}}
  geometry Sphere{}}}
  Transform{
  translation -1 0 0
  scale .2 .4 .2
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 0 1 1}}
  geometry Sphere{}}}
  Transform{
  translation 0 0 1
  scale .2 .4 .2
  rotation 1 0 0 -.5
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 1 0 0}}
  geometry Sphere{}}}
  Transform{
  translation 0 -.5 .9
  scale .4 .1 .3
  children Shape{
  appearance Appearance{material Material
   {diffuseColor 1 1 1}}
  geometry Sphere{}}}
  ]}
  DEF TS TimeSensor{
  cycleInterval 8
  loop TRUE}
  DEF OI OrientationInterpolator{
   key[0 .25 .5 .75 1]
   keyValue [0 1 0 0, 0 1 01.57,0 1 0 3.14
   0 1 0 4.71 0 1 06.28]}
  ROUTE TS.fraction TO OI.fraction
  ROUTE OI.value TO T.rotation
  Background {skyColor 1 1 1}
  //end of Ex4_03.wrl
  ------------------------------
  //Ex4_03.java
  import java.applet.Applet;
  import java.awt.BorderLayout;
  import com.sun.j3d.utils.applet.MainFrame;
  import com.sun.j3d.utils.geometry.Cone;
  import com.sun.j3d.utils.geometry.Sphere;
  import com.sun.j3d.utils.geometry.Primitive;
  import com.sun.j3d.utils.universe.*;
  import javax.media.j3d.*;
  import javax.vecmath.*;
  public class Ex4_03 extends Applet{
  public BranchGroup createSceneGraph() {
  BranchGroup objRoot = new BranchGroup();
  Transform3D t3d = new Transform3D();
  t3d.setScale(0.3);
  TransformGroup objScale = new TransformGroup();
  objScale.setTransform(t3d);
  Transform3D temp = new Transform3D();
  TransformGroup obj = new TransformGroup();
   obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   obj.setTransform(temp);
  objScale.addChild(obj);
  Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
  0, 0,
  4000, 0, 0,
  0, 0, 0);
  RotationInterpolator rotator =
  new RotationInterpolator(rotationAlpha, obj, temp,
   0.0f, (float) Math.PI*2.0f);
  BoundingSphere bounds =
  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
  rotator.setSchedulingBounds(bounds);
  obj.addChild(rotator);
  objRoot.addChild(objScale);
  Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
  Vector3f light1Direction= new Vector3f(4.0f, -7.0f, -12.0f);
  DirectionalLight light1
  = new DirectionalLight(light1Color, light1Direction);
  light1.setInfluencingBounds(bounds);
  objRoot.addChild(light1);
  Appearance app_red = new Appearance();
  Material material1 = new Material();
  material1.setDiffuseColor(new Color3f(1.0f,0.0f,0.0f));
  app_red.setMaterial(material1);
  Appearance app_yellow = new Appearance();
  Material material2 = new Material();
  material2.setDiffuseColor(new Color3f(1.0f,1.0f,0.0f));
  app_yellow.setMaterial(material2);
  Appearance app_blue = new Appearance();
  Material material3 = new Material();
  material3.setDiffuseColor(new Color3f(0.0f,0.0f,1.0f));
  app_blue.setMaterial(material3);
  Appearance app_cyan = new Appearance();
  Material material4 = new Material();
  material4.setDiffuseColor(new Color3f(0.0f,1.0f,1.0f));
  app_cyan.setMaterial(material4);
  Appearance app_white = new Appearance();
  Material material5 = new Material();
  material5.setDiffuseColor(new Color3f(1.0f,1.0f,1.0f));
  app_white.setMaterial(material5);
  Cone c = new Cone(1.0f,2.0f,1,app_red);
  Primitive s_1 = (Primitive) new Sphere(1.0f,app_yellow);
  Primitive s_2 = (Primitive) new Sphere(.2f ,app_blue);
  Primitive s_2b = (Primitive) new Sphere(.2f ,app_blue);
  Primitive s_3 = (Primitive) new Sphere(1.0f,app_cyan);
  Primitive s_3b = (Primitive) new Sphere(1.0f,app_cyan);
  Primitive s_4 = (Primitive) new Sphere(1.0f,app_red);
  Primitive s_5 = (Primitive) new Sphere(1.0f,app_white);
  Transform3D t1 = new Transform3D();
   t1.setScale(new Vector3d(1,1.2,1));
  TransformGroup objTrans1 = new TransformGroup(t1);
   objTrans1.addChild(s_1);
  Transform3D t2 = new Transform3D();
  t2.setScale(new Vector3d(1,1,2));
  t2.setTranslation(new Vector3f(0.5f, 0.4f, 0.6f));
  TransformGroup objTrans2 = new TransformGroup(t2);
  objTrans2.addChild(s_2);
  Transform3D t3 = new Transform3D();
  t3.setScale(new Vector3d(1,1,2));
  t3.setTranslation(new Vector3f(-0.5f, 0.4f, 0.6f));
  TransformGroup objTrans3 = new TransformGroup(t3);
  objTrans3.addChild(s_2b);
  Transform3D t4 = new Transform3D();
  t4.setScale(new Vector3d(1.1,0.4,1.1));
  t4.setTranslation(new Vector3f(0.0f, 1.0f, 0.0f));
  TransformGroup objTrans4 = new TransformGroup(t4);
  objTrans4.addChild(c);
  Transform3D t5 = new Transform3D();
  t5.setScale(new Vector3d(0.2, 0.4, 0.2));
  t5.setTranslation(new Vector3f(1.0f, 0.0f, 0.0f));
  TransformGroup objTrans5 = new TransformGroup(t5);
  objTrans5.addChild(s_3);
  Transform3D t6 = new Transform3D();
  t6.setScale(new Vector3d(0.2, 0.4, 0.2));
  t6.setTranslation(new Vector3f(-1.0f, 0.0f, 0.0f));
  TransformGroup objTrans6 = new TransformGroup(t6);
  objTrans6.addChild(s_3b);
  Transform3D t7 = new Transform3D();
  t7.setScale(new Vector3d(0.2, 0.4, 0.2));
  t7.setTranslation(new Vector3f(0.0f, 0.0f, 1.0f));
  TransformGroup objTrans7 = new TransformGroup(t7);
  objTrans7.addChild(s_4);
  Transform3D t8 = new Transform3D();
  t8.setScale(new Vector3d(0.4, 0.1, 0.3));
  t8.setTranslation(new Vector3f(0.0f, -0.5f, 0.9f));
  TransformGroup objTrans8 = new TransformGroup(t8);
  objTrans8.addChild(s_5);
  Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
  Background bg = new Background(bgColor);
  bg.setApplicationBounds(bounds);
  objRoot.addChild(bg);
  obj.addChild(objTrans1);
  obj.addChild(objTrans2);
  obj.addChild(objTrans3);
  obj.addChild(objTrans4);
  obj.addChild(objTrans5);
  obj.addChild(objTrans6);
  obj.addChild(objTrans7);
  obj.addChild(objTrans8);
  objRoot.compile();
  return objRoot;
  }
  public Ex4_03() {
  setLayout(new BorderLayout());
  Canvas3D c = new Canvas3D(null);
  add("Center", c);
  BranchGroup scene = createSceneGraph();
  SimpleUniverse u = new SimpleUniverse(c);
  u.getViewingPlatform().setNominalViewingTransform();
  u.addBranchGraph(scene);
  }
  public static void main(String[] args) {
  new MainFrame(new Ex4_03(), 640, 480);
  }
  }
  //end of Ex4_03.java
  我们来仔细研究JAVA3D所提供的形体几何变换功能。前面我们主要介绍形体生成的方
法,其中,编写自己的形体用到的是Shape3D对象,VRML97与之对应的是Shape节点。同样
,JAVA3D对应于VRML97的Transform节点的对象是Transform3D。
  VRML97编程中,形体的平移可以通过Transform节点的translation字段来设置;JAVA
3D编程时,形体的平移可以通过Transform3D的setTranslation方法完成。
  VRML97编程中,形体的旋转可以通过Transform节点的rotation字段来设置;JAVA3D编
程时,形体的旋转可以通过Transform3D的setRotation方法完成。
  VRML97编程中,形体的比例变化可以通过Transform节点的scale字段来设置;JAVA3D
编程时,形体的比例变化可以通过Transform3D的setScale方法完成,其中,当扩弧里只有
一个双精度数时,setScale对所有的方向均采用同一个比例,而当里面有三个双精度数时
,setScale对不同的方向可以采用不同的比例,双精度数后面不加符号,而单精度浮点数
后面要加一个f。
  我们来看一下程序的主要内容:
  程序一开始就定义了一个BranchGroup,后面所有的生成的内容如形体、形体的变换、
背景、灯光都放入其中。
  为了使我们生成的图形有合适的大小,我们定义了一个TransformGroup对象objScale
,通过一个t3d使其按比例缩小,这相当于我们将视野往后移动。
  为了使我们生成的小丑能够旋转,我们定义一个TransformGroup类型的obj,这相当于
定义了一个小丑所在的局部坐标系,设定此坐标系可以旋转,选转方式由一个Transform3
D类型的temp来确定,定义obj为objScale的一个子节点。
  通过定义rotationAlpha、rotator地定义使得obj能够产生旋转。它们的作用类似于V
RML的时间传感器及方向内插器。
  接下来我们在空间中定义了一个定向光、各种材质、形体,并将灯光、具有一定材质
的形体放入objRoot、obj之中,最后我们还定义了一个背景光。
  通过这个程序的编写,我们把握了JAVA3D生成复杂形体的最基本概念,即如何进行形
体的几何坐标变换。把握了形体几何坐标变换方法,我们就具有了编写JAVA3D复杂应用程
序的能力。(完)



本文地址:http://www.cg3000.com/html/cgTutorials/VirtualReality/Java3D/20071205/JAVA3Dxuexixilie_69312.shtml

上一篇:JAVA3D学习系列1--7
下一篇:Kaon Activate!3D Author使用指南-程序安装
关键字:迅雷 快车 Baidu JAVA 学习 系列
最新评论共有 2 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
图腾CG联盟免责声明:本网站转载纯粹出于为网民传递更多信息之目的,无任何商业目的。如本网站转载稿件涉及版权等问题,请作者速来函admincg3000@163.com联系,在此,我们首先向您表示诚挚的歉意,并将尽快予以改正。本网站上发表的内容只代表作者本人之观点,本网站只出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。
赞助广告