Java 版 (精华区)
发信人: bali (阿奔), 信区: Java
标 题: JAVA3D学习系列之7---点的生成
发信站: 紫 丁 香 (Fri Mar 24 10:59:55 2000), 转信
信人: vrml (3d), 信区: Java
标 题: JAVA3D学习系列(7)--点的生成
发信站: BBS 水木清华站 (Wed Apr 7 16:18:25 1999)
JAVA3D学习系列之7---点的生成
汕头大学机电系 张杰(jzhang@mailserv.stu.edu.cn)
( 在前面(第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 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中了。
二. 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.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
六. 能够旋转的点
前面介绍的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米之内的形体
均可以旋转运动,而在这范围之外的所有形体均不产生运动。
和Point5.java相类似的VRML程序如下,VRML里的点不能够
改变大小:
//Point5.wrl
#VRML V2.0 utf8
DEF T Transform{
children 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 ]}
}}}
DEF TS TimeSensor{
cycleInterval 4
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 1, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
# end of Point5.wrl
--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.118.243.89]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:206.779毫秒