原文地址:http://blog.csdn.net/gaoyunpeng/article/details/1771473
本文重新整理格式、补充、删改,转载发布
生成简单或复杂的形体(也可以直接调用现有的三维形体) 使形体具有颜色、透明效果、贴图。 可以在三维环境中生成灯光、移动灯光。 可以具有行为(Behavior)的处理判断能力(键盘、鼠标、定时等) 可以生成雾、背景、声音等。 可以使形体变形、移动、生成三维动画。 可以编写非常复杂的应用程序,用于各种领域如VR。 在编写JAVA3D程序之前,我们需要了解一些概念,完成一些准备工作。
场景图中有许多线和线的交汇点,交汇点称为节点(Node),不管什么节点,它都是JAVA3D类的实例(Instance of Class),线(Arc)表示实例之间的关系。
在JAVA3D的场景图中,最底层(根部)的节点是Virtual Universe,每一个场景图只能有一个Virtual Universe。 在Virtual Universe上面,就是Locale节点,每个程序可以有一个或多个Locale,但同时只能有一个Locale处于显示状态,就好象一个三维世界非常大,有很多个景点,但我们同时只能在一个景点进行观察。当然我们可以从一个景点跳到另一个景点,不过绝大多数程序只有一个Locale。 每一个Locale上面拥有一个到多个BranchGroup节点。我们知道,要想建立我们的三维应用环境,我们必须建立所需要的形体(Shape),给出形体的外观(Appearance)及几何信息(Geometry),再把它们摆放在合适的位置,这些形体及其摆放位置都建立在BranchGroup节点之上,摆放位置通过另一个节点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
略
(环境配置请参考http://blog.csdn.net/olenet/article/details/21334219)//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
略
根据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的核心部分一个基本体也没有定义,但JAVA3D所附带的Utility为我们提供了一些事先编好的基本体,我们可以调用这些基本体。 第五个import语句表示我们调用一些设置基本的观测位置所用的类,如SimpleUniverse、Viewer、ViewingPlatform等,利用它们,我们可以很方便地构造JAVA3D场景图底部的VirtualUniverse、Locale及其上的View分支,进而使精力主要用在建模及复杂问题的处理上面,当然它们也都是JAVA3D所附带的Utility。 第六个import语句表示调用程序所需要的JAVA3D核心类,因而所有JAVA3D程序都必须带有这一语句,只有这样才能在JDK1.2环境中编译执行JAVA3D程序。 第七个import语句表示调用程序所需要的定义矢量计算所用的类。
//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对程序进行了优化,程序的运行运行速度最快。不过在一些场合,如形体在程序运行过程中才生成,则不能Compile形体,这说明优化是有条件的。注意,JAVA3D程序没有“开始渲染”这一步骤,当一个View被有效地放入一个Virtual Universe,JAVA3D运行环境就开始不停地渲染JAVA3D场景图中的三维形体,从而使屏幕上显示出三维图形。
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。
为了使我们的程序既可以为applet程序,又可以为application程序,我们可以通过编写一个main方法,利用import语句提供的MainFrame类,生成一个MainFrame对象,从而使程序变成为application程序。MainFrame是JAVA3D为我们提供的一个非常有用的Utility。介绍了一个简单的JAVA3D程序后,我们开始学习JAVA3D的编程技术。首先我们介绍三维基本形体的生成。和VRML不同,JAVA3D没有基本形体类,因而在程序中无法直接生成大量应用的基本形体,如BOX、CONE、SPHERE等。我们可以通过复杂的编程生成这些基本形体,也可以直接调用JAVA3D为我们提供的geometry classes,利用它生成程序所需要的BOX、COLORCUBE、CONE、SPHERE、CYLINDER。我们开辟一个新的章节介绍这些基本体的生成方法。
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里的Primitive.java中获得。
1.点的生成
下面我们改用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 Platform)。一般来说,表示观测位置的分支可以用JAVA3D的UTILITY来完成,因而我们可以看到,在Point1.java中,构造函数Point1和前面介绍的SimpleCone.java的构造函数SimpleCone内容完全一样。两个程序的不同之处在于形体构造及处理分支,即createSceneGraph方法的定义。 我们来看一下Point1.java的createScendGraph方法的定义。在这个方法里,程序先定义了一个分支objRoot,然后用数组的形式定义了六个顶点坐标vert和六种颜色color,再用PointArray定义了一组点point,并将顶点坐标及颜色赋值给point,由于JAVA3D中的PointArray点是Shape3D的子类,它不能直接放入一个BranchGroup,因而我们还要先定义一个Shape3D对象shape,再将point赋予shape,这样point就可以放入BranchGroup类型的对象objRoot中了。
2. 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表示最终应生成的点的个数。
3. 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
4. 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四个点。
5. 主程序比较简洁的程序Point4.java
前面几个程序,所有的内容均放置在一个程序中,这对于阅读程序来说,增添了一些困难。一般来说,一个具体的例子通常由几个JAVA3D程序来完成,一般是将形体生成部分划为单独的一个子程序,下面我们将上面的Point3.java分成两个程序:子程序myShape.java用来生成点,主程序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
6. 能够旋转的点 前面介绍的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的objRoot里,放置的是一个Group对象。在生成对象的createObject() 方法里,为了使得形体能够产生旋转运动,我们首先建立了一个TransformGroup对象和一个Transform3D对象,通过Capability参数的设置,表示在程序运行时,objTrans能够进行几何变换,并将形体放入objTrans。 JAVA3D之所以能够使形体运动,是因为JAVA3D拥有类似于VRML的时间传感器节点的Alpha对象,和类似于VRML的内插器节点的各种Interpolator对象,它们在由BoundingSphere等对象所设定的范围内在特定的时间内进行几何坐标变化,因而使形体产生运动变化的效果。 本程序中,Alpha给出了一个4秒钟的循环变化时间周期;RotationInterpolator规定了形体每4秒钟绕着Y轴旋转一周。BoundingSphere表示所有距离坐标原点50米之内的形体均可以旋转运动,而在这范围之外的所有形体均不产生运动。
我们可以利用JAVA3D的一些对象,生成各种直线。 可以生成直线的对象有:
1. LineArrayLineArray(int vertexCount, int vertexFormat)2. LineStripArrayLineStripArray(int vertexCount ,int vertexFormat,int[] stripVertexCounts )3. IndexedLineArrayIndexedLineArray(int vertexCount, int vertexFormat, int indexCount )4. IndexedLineStripArrayIndexedLineStripArray( int vertexCount, int vertexFormat,int indexCount, int stripIndexCounts[])
1. 利用LineArray生成直线
LineArray对象的定义如下: LineArray(int vertexCount, int vertexFormat) 这里: vertexCount表示顶点的个数(必须为偶数) vertexFormat表示顶点的格式(第七讲有介绍) 由下面的程序我们得知,Line1.java和前面介绍的Point4.java几乎完全一样,lineShape1.java和pointShape.java也相差不多。运行Line1.java我们获得了三条直线,由此得知,LineArray的作用是生成多条直线,顶点坐标数组的每一对数据构成一条直线。 在编写LineArray生成的直线时,要注意,顶点及颜色的个数必须相等且为偶数,此数目必须赋值于vertexCount,也即程序中的vertexCount必须为偶数且不能少于顶点的个数。 -------------------------- 第一条 ---------------- 第二条 -------------------------- 第三条 我们可以根据各种不同的情况,生成不同的直线,如给定宽度的直线、虚线等。相应的的方法有: setLineWidth(float lineWidth) setLinePattern(int linePattern) setLineAntialiasingEnable(boolean state) 对于线型linePattern有以下数据可选: int PATTERN_SOLID int PATTERN_DASH int PATTERN_DOT int PATTERN_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
2. 利用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多了一个StripCount数组,它可以用来生成多个折线段,下面的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
3. 利用IndexedLineArray生成直线 IndexedLineArray对象的定义为: IndexedLineArray(int vertexCount, int vertexFormat,int indexCount ) 这里: vertexCount表示顶点数组里顶点的个数 vertexFormat表示顶点的格式(第七讲有介绍) indexCount表示选用的顶点个数,如果一个点用了几次,则要把几次加进去 在上一节里我们介绍了利用IndexedPoint生成点的程序,和IndexedPoint相类似,我们可以利用IndexedLineArray生成直线段。 下面的lineShape4.java利用了IndexedLineArray从六个点中挑选了3个点,生成了2条直线。 从程序中我们可以看到,下标为0的点使用了两次,但生成的是两条线,因而参数VertexCount应为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
4. 利用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个点用了两次,因而程序中的vertexCount为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);
}
}
1. 生成平面的对象及其定义
JAVA3D可通过编程显示出面来,面有两种:三角形和四边形,相应的对象为Triangle和Quad。 JAVA3D用于生成平面的对象有:
1. TriangleArrayTriangleArray (int vertexCount, int vertexFormat )2. QuadArrayQuadArray (int vertexCount, int vertexFormat )3. TriangleStripArrayTriangleStripArray ( int vertexCount , int vertexFormat, int[] stripVertexCounts )4. TriangleFanArrayTriangleFanArray ( int vertexCount ,int vetexFormat, int[] stripVertexCounts )5. IndexedTriangleArrayIndexedTriangleArray (int vertexCount , int vertexFormat, int indexCount)6. IndexedQuadArrayIndexedQuadArray (int vertexCount , int vertexFormat, int indexCount )7. IndexedTriangleStripArrayIndexedTriangleStripArray( int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[])8. IndexedTriangleFanArrayIndexedTriangleFanArray ( int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[])
2. 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,
};
public triShape1() {
TriangleArray tri = new TriangleArray(9,
TriangleArray.COORDINATES|TriangleArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
this.setGeometry(tri);
}
}
//end of triShape1.java
从程序运行结果可以得知,TriangleArray将一个顶点数组的每三个数组合在一个,生成一个面,因而vertexCount的点数必须为三的倍数。triShape1.java显示的结果是三个三角形构成的面。由于对每一个顶点都定义了颜色,因而程序显示的是色彩变化的三角形,且只能从正面看到,反面看不到,这和VRML程序生成面的效果完全一样。在VRML程序中,为了使一个面的正反方向都可见,可以在IndexedFaceSet节点中将solid字段设为FALSE。 如何将triShape1.java显示的内容从色彩变化及单面显示变为每一个面只有一种颜色及双面显示?在JAVA3D程序中我们有一个笨办法处理颜色问题,即将每一个面的三个点的颜色均设定为相同的数值,因为TriangleArray对象没有SetColorIndices(0,index)这一方法,故不能从颜色组中选用颜色。至于双面显示问题,我们可以通过设定PolygonAttributes对象的setCullFace(int cullFace)方法来获得,cullFace可以为:CULL_NONE CULL_FRONT ,CULL_BACK通过选择其中之一,来获得前面、后面及双面的显示效果,缺省值为只显示前面。 另外,我们还可以通过设定PolygonAttributes对象的setPolygonMode(int polygonMode)方法使面用顶点或端线来代替。polygonMode有下列三种选择:POLYGON_POINT,POLYGON_LINE ,POLYGON_FILL缺省值为POLYGON_FILL。
triShape2.java显示的是前后都可以看得见的面,每一个面都有唯一的颜色。
//triShape2.java
import javax.media.j3d.*;
public class triShape2 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[] = {
1.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
};
public triShape2() {
TriangleArray tri = new TriangleArray(9,
TriangleArray.COORDINATES|TriangleArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
//pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
// 增加这一行会使面由线代替
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
}
}
3. QuadArray生成的面
QuadArray对象的定义如下: QuadArray (int vertexCount, int vertexFormat )
这里,每一个参数的含义都和TriangleArray里的一样。 QuadArray可用来生成平面,构成平面的顶点的数目必须为4的倍数。下面我们来看一个利用QuadArray的例子,例子里有8个点,程序运行后生成了两个长方形面。
//quadShape1.java
import javax.media.j3d.*;
public class quadShape1 extends Shape3D {
private float vert[] = {
-.6f , .8f ,0.0f,
-.6f , -.8f,0.0f,
-0.2f , -.6f,0.0f,
-0.2f , .6f ,0.0f,
0.2f , .8f ,0.0f,
0.6f , .8f, 0.0f,
0.6f , -.8f, 0.0f,
0.2f , -.8f,0.5f,
};
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,
};
public quadShape1() {
QuadArray tri = new QuadArray(8,
QuadArray.COORDINATES|QuadArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
this.setGeometry(tri);
}
}
//end of quadShape1.java
程序的双面显示问题及单一颜色问题的处理同上面的triShape2.java。 编写QuadArray应用程序时,我们要注意几个问题。首先是四点应当共面,如果不共面,程序仍然可以编译运行,但显示的内容为两个三角面。 其次是四个点组成的面不应有凹点,这有点象VRML程序中的Extrusion、IndexedFaceSet里的情况,当然,在VRML程序中四个点构成的面可以有凹点,这时只需要在相应的节点内加上一个参数
:
convex TRUE
而在JAVA3D程序中,如果QuadArray生成的面有凹点时,程序的显示结果会不正确,例如,当我们将quadShape里的顶点坐标换为:
private float vert[] = {
-.6f , .8f , 0.0f,
-.6f , -.8f , 0.0f,
-0.2f, -.6f , 0.0f,
-0.5f, .0f , 0.0f,
0.2f , .8f , 0.0f,
0.6f , .8f , 0.0f,
0.6f , -.8f , 0.0f,
0.2f , -.8f , 0.5f,
};
时,显示的结果不确定,正面时是一个形状,转到反面时是另一个形状。最后一个问题是QuadArray所利用的每四个点,其坐标位置除了要共面、凸点,四个点的旋转方向也要注意,如果点的旋转方向是逆时针的话,其正面朝外,反之则朝内。当我们将顶点的坐标换成下面的数据时,我们可以清楚地得出这一结论。
private float vert[] = {
-.6f , .8f ,0.0f,
-.6f , -.8f ,0.0f,
-0.2f , -.4f ,0.0f,
-0.2f , .4f ,0.0f,
0.2f , .8f ,0.0f,
0.6f , .8f ,0.0f,
0.6f , -.8f ,0.0f,
0.2f , -.8f ,0.5f,
};
下面的程序中,我们利用一组点,生成了两组三角片面。程序中,顶点数组的个数为11,头一组用了7个顶点,生成了5个相连的三角片面,后一组用了5个顶点,生成了三个相连的三角片面。
//triShape3.java
import javax.media.j3d.*;
public class triShape3 extends Shape3D {
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
5. 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
//end of lineShape5.java
JAVA3D是SUN公司为我们提供的一个API,里面包含了几乎所有我们所需要的编写JAVA三维多媒体应用程序的基本的类及方法。我们在编程时,只 需调用所需要的类及方法,就可以快速地编写出复杂的三维多媒体应用程序。可以说,我们所做的工作只是学会应用JAVA3D的各种类(Objects)及方 法。 JAVA3D为我们提供了100多个存放于javax.media.j3d程序包中的类,它们被称为JAVA3D的核心类,除了核心包中的类以外,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程序还必需用到下面两个包:java.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场景图所引用,如某一个颜色可以被多个形体所引用。 |