赞
踩
要是实现自己的图形,必须要用到Shape3D类。
The Shape3D leaf node specifies all geometric objects. It contains a list of one or more Geometry component objects and a single Appearance component object. The geometry objects define the shape node's geometric data. The appearance object specifies that object's appearance attributes, including color, material, texture, and so on.
要实现自己的图形,需要为shape3D提供Geometry 和 Appearance。
点、线、面的生成需要的条件“
1.需要给出顶点坐标数组及顶点坐标对应的颜色数组
2.点、线、面是GeometryArray的子类或孙类,因而继承了它所有的方法。
3.由于Geometry的对象都是几何对象,不能单独放在三维场景图里面,因为只有三维形体才能显示出三维的效果,只有点,线,面的对象是看不出 三维效果的。必须将点、线、面等几何对象赋予shape3D这样(Leaf类的子类)的几何形体,才可以在三维场景中显示。像 Cone.Box,Cylinder,Sphere等对象已经属于形体,所以他们可以直接用在三维场景中。
下面介绍Geometry及其父类和子类的关系
GeometryArray的构造方法:
GeometryArray(int vertexCount, int vertexFormat);
vertexCount:顶点数组里的个数
vertexFormat可以为:
COORDINATES 顶点坐标数组 COLOR_3 不带Alpha值的颜色数组 //此两个经常用到
COLOR_4 带Alpha值的颜色数组 NORMALS 顶点法向数组
Texture_Coordinate_2 二维纹理坐标数组 Texture_Coordinate_3 三维纹理坐标数组
使用这些时,前面都要加上具体的类名和”.“
Geometry的常用方法有:
setCoordinate(int index,float coordinate[]) ; setColor(int index, float color[]) //index为索引开始下标,一般为0
setTextureCoordinate(int index, Point2f textcoord) //此方法很少用到
上述三种方法都有对应的Get方法。其内参数相同,此处就不再一一写出来了
《二》GeometryArray在介绍以上2个Point对象之前,先介绍一下PointAttributes对象,从该对象名就可以看出该对象是用来Point对象设置属性,如大小,显示形状(即显示效果)等。
PointAttributes设置点的大小及显示效果的主要方法:
SetPointSize(float pointSize);
SetPointAntialiasingEnable(boolean state) //当state=true时,point为圆形,当state=false时,point的形状为方形,默认情况下state=false.
PointAttributes有4个flags:
ALLOW_SIZE_READ ALLOW_SIZE_WRITE ALLOW_ANTIALISING_READ ALLOW_ANTIALISING_WRITE
这些flags可用于交互式编程中,使点的大小及形状在程序运行时改变,产生点的动态变化效果
PointArray对象
PointArray对象的构造方法: PointArray(int vertexCount, int vertexFormat)
vertexFormat的使用可参照点、线、面的生成(一)
vertexCount表示数组里顶点的个数,当其个数大于实际提供的顶点个数时,多余的点数将被默认为是位置: (0.0f,0.0f,0.0f),即显示在原点,即使有多个多余的点,都将累计显示在原点,我们看到的就将会是一个点。若vertexCount少于实 际提供的点数时,程序将出现错误。但是当vertexCount的数目小于给定的颜色数组个数时,将正常显示。
举例如下:
例1:
import java.applet.Applet;
import java.awt.BorderLayout;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class Point1 extends Applet{
public BranchGroup createSceneGraph()
{
BranchGroup objRoot=new BranchGroup();
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100); //定义背景的有效范围
Color3f bgcolor=new Color3f(1.0f,1.0f,1.0f);
Background bg=new Background(bgcolor); //设定背景颜色
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
float vert[]=
{
0.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,
0.0f,1.0f,0.5f,
};
int vCount=6;
Shape3D shape=new Shape3D(); //定义形体
PointArray point=new PointArray(vCount,PointArray.COORDINATES|PointArray.COLOR_3); //定义形体的几何参数
point.setCoordinates(0, vert);
point.setColor(0, color);
PointAttributes pa=new PointAttributes(); //定义点的特征
pa.setPointSize(10.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 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 Rotate(),400,300);
}}
该程序的显示结果为: 当vCount>=7时,图形的显示效果如下:
IndexedPointArray对象
IndexedPointArray对象的构造函数为:PointArray(int vertexCount, int vertexFormat, int indexCount)
该对象可以在多个顶点中选择部分或全部顶点,并将其以指定的颜色显示
indexCount:用于表示从顶点坐标数组中选取需要显示的点的个数。因此,程序中还需要定义一个数组,存放所挑选的顶点的下标值。
正因为有indexCount,IndexedPointArray对象相对于PointArray对象就多了两个方法:
setCoordinateIndices(int index, int indexCount), setColorIndices(int index, int indexCount) //indexCount是选取的要显示的点的个数
将上述代码的蓝色部分修改为一下代码即可达到效果:
int[] index={0,2,5,3};
int indexCount=4;
IndexedPointArray point=new IndexedPointArray(vCount,IndexedPointArray.COORDINATES|IndexedPointArray.COLOR_3,indexCount);
point.setCoordinates(0, vert);
point.setColor(0, color);
point.setCoordinateIndices(0, index);
point.setColorIndices(0, index);
PointAttributes pa=new PointAttributes();
pa.setPointSize(10.0f);
pa.setPointAntialiasingEnable(true);
显示的效果如下:
《四》线
Java3D提供的API中,生成的直线对象有:
LineArray IndexedLineArray LineStripArray IndexedLineStripArray //后两个对象是与折线相关的
在介绍直线之前,先介绍一下直线属性的设置对象:LineAttributes对象
其构造方法为LineAttributes()或LineAttributes(float lineWidth, int linePattern , boolean lineAntialiasing)
linePattern 包括:pattern_solid , pattern_dash, pattern_dot, pattern_dash_dot
lineAntialiasing 为true时,显示的直线是经过修饰的,有光滑的边缘,而当lineAntialiasing=false或默认时,显示的是长方体的直线,即有很明显的边缘。
LineAttributes有6个flags,分别是lineWidth,linePattern ,lineAntialiasing的读和写,可参照PointAttribute,起作用也与PointAttribute相同
LineAttributes的主要方 法:setLineWidth(float lineWidth), setLinePattern(int linePattern), setLineAntialiasingEnable(boolean state)
LineArray对象
LineArray的构造方法:LineArray(int vertexCount, int vertexFormat)
要求:1.用于生成多条直线,按下标顺序每两个顶点定义一条直线,点无重叠,除非在实际定义点的坐标时将同一个点定义多次。
2.顶点及颜色的个数必须相等且必须为偶数(因为两个点才能构成一条直线),(这一点在PointArray中没有要求,当实际颜色的个数多于实际顶点的个数时也能正常显示)
3.vertexCount不能小于实际提供的顶点个数,这一点和PointArray中相同
示例如下:
模块:将共同需要用到的方法放入一个类中,将Shape3D图形生成的方法放入另一个类中,避免重复的工作
共同类:import java.applet.Applet;
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class Line1 extends Applet{
private BranchGroup createSceneGraph()
{
BranchGroup objRoot=new BranchGroup();
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
Color3f bgColor=new Color3f(1.0f,1.0f,1.0f);
Background bg=new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
Shape3D shape=new lineShape();
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Line1()
{
setLayout(new BorderLayout());
GraphicsConfiguration config=SimpleUniverse.getPreferredConfiguration();
Canvas3D c=new Canvas3D(config);
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 wind(),600,600);
}
}
调用lineShape类生成LineArray的Shape3D图形:
import javax.media.j3d.*;
public class lineShape extends Shape3D{
private float vert[]=
{
-0.6f,0.4f,0.0f, -0.6f,-0.4f,0.0f,
-0.2f,0.4f,0.0f, -0.2f,-0.4f,0.0f,
0.2f,0.4f,0.0f, 0.2f,-0.4f,0.0f,
0.6f,0.4f,0.0f, 0.6f,-0.4f,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.5f,0.3f,0.3f, 0.0f,0.4f,0.1f,
};
public lineShape()
{
LineArray line=new LineArray(8,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);
}
}
显示效果如下: 若将vert[]数组中的坐标( -0.2f,0.4f,0.0f, )改为(-0.6f,-0.4f,0.0f,)则会共用第二个点,效果如下:
LineStripArray对象
构造函数:LineStripArray(int vertexCount,int vertFormat, int[] StripVertexCounts) //用于生成多条折线,每条折线有2个或多个点构成
StripVertexCounts为一个数组,数组里的每一个值表示每条折线所拥有的顶点数目
将上述lineShape()函数中蓝色的部分代码改为如下:
int sCount[]=new int[2];
sCount[0]=3;
sCount[1]=3;
LineStripArray line=new LineStripArray(8,LineStripArray.COORDINATES|LineStripArray.COLOR_3,sCount);
则显示的效果如下(按点的顺序显示,不重叠,除非重复定义某个点,和上面的理论一样)
IndexedLineArray对象
构造方法为:IndexedLineArray(int vertextCount, int vertexFormat, int indexCount)
作用:用于从多个点中选择特定的点生成多条直线,所挑选的坐标下标要放在一个数组中
indexCount:表示选用的顶点个数,若一个点用了多次,则要按多次计算
若要从上述lineShape类中挑选4各点来显示:则蓝色部分代码替换如下:
int indexCount=4; //所选下标个数,包括重复的选择
int[] index={0,1,1,4}; //存放所挑选的下标值
IndexedLineArray line=new IndexedLineArray(8,IndexedLineArray.COORDINATES|IndexedLineArray.COLOR_3,indexCount);
line.setCoordinateIndices(0, index);//定义要显示的点的坐标
line.setColorIndices(0, index);//定义要显示的点的颜色
显示效果如下:
IndexedLineStripArray对象
构造函数如下:IndexedLineStripArray(int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[])
作用:从顶点坐标数组中选择部分顶点,将其分成几组,每个组的各个顶点链接起来,生成相应的折线,程序中需要定义一个数组来存放做选顶点的下标
stripIndexCount为一数组,数组里每一个值表示每条折线所拥有的顶点数
将上述lineShape中蓝色部分该为如下代码:
int indexCount=7;
int[] sCount=new int[2];
int[] index={0,2,1,6,4,1,3};
sCount[0]=3;
sCount[1]=4;
IndexedLineStripArray line=new IndexedLineStripArray(8,IndexedLineStripArray.COORDINATES|IndexedLineStripArray.COLOR_3,indexCount,sCount);
line.setCoordinateIndices(0, index);//定义要显示的点的坐标
line.setColorIndices(0, index);//定义要显示的点的颜色
显示效果如下:
注:除非重复定义了某个点,否则每个点只被使用一次,即直线与直线之间,或折线与折线之间不会相连接。若重复定义了n此,则点被重复使用n此
《五》面同样,在介绍面的生成前,先介绍一下面的基本属性设置方法:PolygonAttributes对象
PolygonAttributes的构造方法有:
PolygonAttributes()
PolygonAttributes(int polygonMode, int cullFace, float polygonOffset)
PolygonAttributes(int polygonMode, int cullFace, float polygonOffset, boolean backFaceNormalFlip)
为了使程序在运行时产生特定的变化效果,可通过setCapability的方法设定一下flags来达到:
ALLOW_CULL_FACE_READ , ALLOW_CULL_FACE_WRITE, ALLOW_MODE_READ, ALLOW_MODE_WRITE
ALLOW_OFFSET_READ, ALLOW_OFFSET_WRITE, ALLOW_NORMAL_FLIP_READ, ALLOW_NORMAL_FLIP_WRITE,
PolygonAttributes经常使用的方法有:
setCullFace(int cullFace), setPolygonMode(int polygonMode);
cullFace有三个值可使用:CULL_BACK(默认值,只能看到正面) CULL_NONE(正反面均能看到) CULL_FRONT(只能看到反面)
对于三个点构成的面,判断正、反面的法则: 用右手螺旋法则,右手绕着3个点的顺序抓过去,大拇指所指的方向即为正向,在默认情况下,当正方向指向观察者的方向时,图像可显示,当正方向背离观察者时,图形不可显示。
polygonMode也有3个值可以使用:
POLYGON_FILL(缺省值,以面的形式表示)
POLYGON_POINT(以点的形式表示) ,在给定的坐标处用点表示,点与点之间不链接,此方法的显示效果也可以通过PointArray来达到。
POLYGON_LINE(以顶点连线的形式来表示) ,顶点与顶点之间用线链接,相当于该图形没有没填充,用LineArray也能达到同样的显示效果,只是相对比较复杂一点。
Java3D提供的API中,生成平面的对象有:
TriangleArray, QuadArray, TriangleStripArray, IndexedQuadArray, IndexedTriangleArray, IndexedTriangleStripArray, IndexedTriangleFanArray
TriangleArray对象
构造方法:TriangleArray(int vertexCount, int vertexFormat)
vertexCount:顶点数组的个数,因为表示的是三角形的面,所以顶点的个数必须为3的倍数
QuadArray对象
构造函数:QuadArray(int vertexCount, int vertexFormat)
该对象用来生成平面,构成平面的顶点必须是四的倍数,每四个顶点构成一个平面。
注意:1.四点应当共面,如果不共面,程序仍然可以编译,但显示的内容为2个三角面
2.四个点组成的面不应该有凹点,如果有凹点,程序的显示结果会比较奇怪。
TriangleStripArray对象
构造函数:TriangleStripArray(int vertexCount, int vertexFormat, int[] stripVertexCounts)
与LineStripArray作用相似,该对象用来生成多组三角面,对于每一组三角面来说,它的头三个点生成一个面,从第四个点开始,每一个点和它紧邻的前面的两个点生成一个新的三角面,stripVertexCounts数组的长度,也就是三角面的组数,每一组下标存放的则是每组用到的顶点数
TriangleFanArray对象
构造函数:TriangleFanArray(int vertexCount, int vetexFormat, int[] stripVertexCounts)
作用:同TriangleStripArray对象一样,用来生成多组三角片面,每组三角片面用一定数量的顶点,每个组生成三角片面时,头3个顶点构成一个三角片面,其余的顶点和紧邻前面的一个顶点及每组的第一个顶点生成一个三角片面,stripVertexCounts和TriangleAtripArray具有同样的意义
IndexedTriangleArray对象
构造方法:IndexedTriangleArray(int vertexCount, int vertexFormat, int indexCount)
作用:从一个顶点数组中挑选一些顶点生成所需要的三角片面。indexCount表示生成的面的顶点个数,数值为三角片面个数的3倍,具体挑选的点的下标放在一个数组index里面。图形的构成是从Index里面的点中构成
IndexedQuadArray对象
作用:该对象和IndexedTriangleArray对象基本一样,只是挑选的点要是4的倍数。
IndexedTriangleStripArray对象
构造方法:IndexedTriangleStripArray(int vertexCount, int vertexFormat, int indexCount, int[] stripIndexCounts)
作用:可以生成多组三角片面,该方法综合了IndexedTriangleArray对象的方法和TriangleStripArray对象的方法。从顶点数组中选择要显示的点,将要显示的顶点的数目放在indexCount中,要显示的顶点的下标放在数组index中,index数组中的头3个顶点生成一个三角面,从第四个开始,每一个点都和紧邻的前面两个点生成一个新的面
IndexedTriangleFanArray对象
其构造方法和IndexedTriangleStripArray对象相似,只是在每组数组生成三角面时,头3个顶点构成一个三角面,从第四个顶点开始,其余的每个顶点和紧邻的前面一个顶点及其每组的第一个顶点构成一个三角面。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。