点击此处,获取更良好的阅读体验
鉴于许多同学对计算机图形学设计作品无法下手,特此推出Java3D设计作品入门级教程,可以给予毫无头绪的你一点思路。本文仅起到抛砖引玉的作用,并不提供现成的作品。
首先我们要理解java3d中的坐标轴,这个坐标轴与我们平常摆的位置的不太一样,所以要做下区分
然后我们把这个坐标轴代入到我们真实的环境中,代码及运行结果如下:
package com.test.demo01;
import java.applet.Applet;
import java.awt.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;
public class BezierSurfaceMerging extends Applet
{public BranchGroup createBranchGroupSceneGraph()
{BranchGroup BranchGroupRoot =new BranchGroup();
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
Color3f bgColor=new Color3f(0f,1.0f,1.0f);
Background bg=new Background(bgColor);
bg.setApplicationBounds(bounds);
BranchGroupRoot.addChild(bg);
Color3f directionalColor=new Color3f(1.f,0.f,0.f);
Vector3f vec=new Vector3f(0.f,0.f,-1.0f);
DirectionalLight directionalLight=new DirectionalLight(directionalColor,vec);
directionalLight.setInfluencingBounds(bounds);
BranchGroupRoot.addChild(directionalLight);
Transform3D tr=new Transform3D();
tr.setScale(0.85);
TransformGroup transformgroup=new TransformGroup(tr);
transformgroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
transformgroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
BranchGroupRoot.addChild(transformgroup);
MouseRotate mouserotate = new MouseRotate();
mouserotate.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mouserotate);
mouserotate.setSchedulingBounds(bounds);
MouseZoom mousezoom = new MouseZoom();
mousezoom.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mousezoom);
mousezoom.setSchedulingBounds(bounds);
MouseTranslate mousetranslate = new MouseTranslate();
mousetranslate.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mousetranslate);
mousetranslate.setSchedulingBounds(bounds);
//定义第一个Bezier曲面的16个控制顶点
float[][][] P1={{{-0.8f,0.9f,-0.4f,1.f},
{-0.2f,0.8f,-0.5f,1.f},
{0.2f,0.9f,-0.4f,1.f},
{0.8f,0.8f,-0.5f,1.f} },
{ {-0.8f,0.7f,-0.4f,1.f},
{-0.2f,0.6f,0.9f,1.f},
{0.2f,0.7f,0.8f,1.f},
{0.8f,0.6f,-0.4f,1.f} },
{{-0.8f,0.4f,-0.4f,1.f},
{-0.2f,0.5f,0.8f,1.f},
{0.2f,0.3f,0.7f,1.f},
{0.8f,0.4f,-0.5f,1.f} },
{ {-0.8f,0.f,-0.8f,1.f},
{-0.2f,0.1f,0.9f,1.f},
{0.2f,0.f,-0.8f,1.f},
{0.8f,0.1f,0.9f,1.f} } };
//定义第一个Bezier曲面外观属性
Appearance app1 = new Appearance();
PolygonAttributes polygona1=new PolygonAttributes();
polygona1.setBackFaceNormalFlip(true);
polygona1.setCullFace(PolygonAttributes.CULL_NONE);
// polygona1.setPolygonMode(PolygonAttributes.POLYGON_LINE);
app1.setPolygonAttributes(polygona1);
ColoringAttributes color1=new ColoringAttributes();
color1.setColor(1.f,0.f,0.f);
app1.setColoringAttributes(color1);
Shape3D BezierSurfaceface1=new BezierThreeOrderSurfaceface(P1,app1);
transformgroup.addChild(BezierSurfaceface1);
BranchGroupRoot.compile();
return BranchGroupRoot;
}
public BezierSurfaceMerging()
{setLayout(new BorderLayout());
GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
Canvas3D c=new Canvas3D(gc);
add("Center",c);
BranchGroup BranchGroupScene=createBranchGroupSceneGraph();
SimpleUniverse u=new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(BranchGroupScene);
}
public static void main(String[] args)
{new MainFrame(new BezierSurfaceMerging(),400,400); }
}
class BezierThreeOrderSurfaceface extends Shape3D
{public BezierThreeOrderSurfaceface(float[][][] P,Appearance app)
{int i,j,k;
int n0;//定义对参数u、v在[0,1]区间的等分点数
float division;//参数u在[0,1]区间的等分线段长度
n0=50;division=1.f/n0;
//分别定义存放控制顶点x、y、z坐标与第四维坐标的数组
float[][] PX=new float[4][4];
float[][] PY=new float[4][4];
float[][] PZ=new float[4][4];
float[][] P4=new float[4][4];
//定义系数矩阵及其转置矩阵
float[][] M1={{1.f,0.f,0.f,0.f},
{-3.f,3.f,0.f,0.f},
{3.f,-6.f,3.f,0.f},
{-1.f,3.f,-3.f,1.f}};
float[][] M2={{1.f,-3.f,3.f,-1.f},
{0.f,3.f,-6.f,3.f},
{0.f,0.f,3.f,-3.f},
{0.f,0.f,0.f,1.f}};
//定义Bezier曲面的u、v参数分割点坐标数组
float[][][] UV=new float[n0+1][n0+1][2];
//定义U、V矩阵数组
float[][] UU=new float[1][4];
float[][] VV=new float[4][1];
//定义存放曲面上点的坐标的数组
float[][][] SurfaceXYZ=new float[n0+1][n0+1][4];
for(i=0;i<n0+1;i++)
for(j=0;j<n0+1;j++)
{ UV[i][j][0]=i*division;
UV[i][j][1]=j*division; }
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{ PX[i][j]=P[i][j][0];
PY[i][j]=P[i][j][1];
PZ[i][j]=P[i][j][2];
P4[i][j]=P[i][j][3]; }
//计算曲面上点的坐标值
for(i=0;i<n0+1;i++)
for(j=0;j<n0+1;j++)
{ UU[0][0]=1.f;
UU[0][1]=UV[i][j][0];
UU[0][2]=UV[i][j][0]*UV[i][j][0];
UU[0][3]=UV[i][j][0]*UV[i][j][0]*UV[i][j][0];
VV[0][0]=1.f;
VV[1][0]=UV[i][j][1];
VV[2][0]=UV[i][j][1]*UV[i][j][1];
VV[3][0]=UV[i][j][1]*UV[i][j][1]*UV[i][j][1];
//计算一点的x坐标
matrixm g0=new matrixm(1,4,4,UU,M1);
matrixm g1=new matrixm(1,4,4,g0.CC,PX);
matrixm g2=new matrixm(1,4,4,g1.CC,M2);
matrixm g3=new matrixm(1,4,1,g2.CC,VV);
SurfaceXYZ[i][j][0]=g3.CC[0][0];
//计算一点的y坐标
matrixm g4=new matrixm(1,4,4,UU,M1);
matrixm g5=new matrixm(1,4,4,g4.CC,PY);
matrixm g6=new matrixm(1,4,4,g5.CC,M2);
matrixm g7=new matrixm(1,4,1,g6.CC,VV);
SurfaceXYZ[i][j][1]=g7.CC[0][0];
//计算一点的z坐标
matrixm g8=new matrixm(1,4,4,UU,M1);
matrixm g9=new matrixm(1,4,4,g8.CC,PZ);
matrixm g10=new matrixm(1,4,4,g9.CC,M2);
matrixm g11=new matrixm(1,4,1,g10.CC,VV);
SurfaceXYZ[i][j][2]=g11.CC[0][0];
//计算一点的第4维坐标
matrixm g12=new matrixm(1,4,4,UU,M1);
matrixm g13=new matrixm(1,4,4,g12.CC,P4);
matrixm g14=new matrixm(1,4,4,g13.CC,M2);
matrixm g15=new matrixm(1,4,1,g14.CC,VV);
SurfaceXYZ[i][j][3]=g15.CC[0][0];
//将齐次坐标转换为三维坐标系坐标,如果第4维为1,则不用除第4维
SurfaceXYZ[i][j][0]=SurfaceXYZ[i][j][0]/SurfaceXYZ[i][j][3];
SurfaceXYZ[i][j][1]=SurfaceXYZ[i][j][1]/SurfaceXYZ[i][j][3];
SurfaceXYZ[i][j][2]=SurfaceXYZ[i][j][2]/SurfaceXYZ[i][j][3];
}
QuadArray BezierQuadsurfaceface = new QuadArray(n0*n0*4,
GeometryArray.COORDINATES|GeometryArray.NORMALS);
int c=0;//以顶点数累加的方式设置顶点的序号
for(i=0;i<n0;i++)
{for(j=0;j<n0;j++)
{//设置一个平面上的4个点
Point3f A=new Point3f(SurfaceXYZ[i][j][0],SurfaceXYZ[i][j][1],
SurfaceXYZ[i][j][2]);
Point3f B=new Point3f(SurfaceXYZ[i][j+1][0],SurfaceXYZ[i][j+1][1],
SurfaceXYZ[i][j+1][2]);
Point3f C=new Point3f(SurfaceXYZ[i+1][j+1][0],SurfaceXYZ[i+1][j+1][1],
SurfaceXYZ[i+1][j+1][2]);
Point3f D=new Point3f(SurfaceXYZ[i+1][j][0],SurfaceXYZ[i+1][j][1],
SurfaceXYZ[i+1][j][2]);
//计算由四个点形成的平面的法向量
Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
Vector3f n = new Vector3f();
n.cross(b, a);
n.normalize();
//设置点的序号
BezierQuadsurfaceface.setCoordinate(c, A);
BezierQuadsurfaceface.setCoordinate(c+1, B);
BezierQuadsurfaceface.setCoordinate(c+2, C);
BezierQuadsurfaceface.setCoordinate(c+3, D);
//设置点的法向量
BezierQuadsurfaceface.setNormal(c, n);
BezierQuadsurfaceface.setNormal(c+1, n);
BezierQuadsurfaceface.setNormal(c+2, n);
BezierQuadsurfaceface.setNormal(c+3, n);
c=c+4;
}}
this.addGeometry(BezierQuadsurfaceface);
this.setAppearance(app);
}}
class BezierSurfaceControlPoints extends Shape3D
{public BezierSurfaceControlPoints(float[][][] P,Appearance app)
{int i,j,k;
QuadArray BeziersurfacecontrolPointsNet =new QuadArray(3*3*4,
GeometryArray.COORDINATES|GeometryArray.NORMALS);
int c=0;
for(i=0;i<3;i++)
{for(j=0;j<3;j++)
{Point3f A=new Point3f(P[i][j][0],P[i][j][1],P[i][j][2]);
Point3f B=new Point3f(P[i][j+1][0],P[i][j+1][1],P[i][j+1][2]);
Point3f C=new Point3f(P[i+1][j+1][0],P[i+1][j+1][1],P[i+1][j+1][2]);
Point3f D=new Point3f(P[i+1][j][0],P[i+1][j][1],P[i+1][j][2]);
Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
Vector3f n = new Vector3f();
n.cross(b, a);
n.normalize();
BeziersurfacecontrolPointsNet.setCoordinate(c, A);
BeziersurfacecontrolPointsNet.setCoordinate(c+1, B);
BeziersurfacecontrolPointsNet.setCoordinate(c+2, C);
BeziersurfacecontrolPointsNet.setCoordinate(c+3, D);
BeziersurfacecontrolPointsNet.setNormal(c, n);
BeziersurfacecontrolPointsNet.setNormal(c+1, n);
BeziersurfacecontrolPointsNet.setNormal(c+2, n);
BeziersurfacecontrolPointsNet.setNormal(c+3, n);
c=c+4;
}}
this.addGeometry(BeziersurfacecontrolPointsNet);
this.setAppearance(app);
}}
class matrixm
{public float CC[][]= new float[4][4];
int ll,mm,kk;
public matrixm(int mmm, int kkk, int nnn,float a[][],float b[][])
{for(ll=0;ll<mmm;ll++)
for(mm=0;mm<nnn;mm++){CC[ll][mm]=0.f;}
for(ll=0;ll<mmm;ll++)
for(mm=0;mm<nnn;mm++)
{for(kk=0;kk<kkk;kk++) CC[ll][mm]=CC[ll][mm]+a[ll][kk]*b[kk][mm];}
}}
在这一长段代码中,只有P1的这16个点是我们要改动的地方,这16个的点共同组成了一个曲面。每个点包含了4个坐标,但其中的1.f
我们是不需要去动的,因此真正有用的是前三个
{X, Y, Z, 1.f}
这里的XYZ就分别对应到上述提到的坐标轴中,那么理解了坐标是怎么使用后,还要将坐标对应到曲面中。
为了方便演示,我们将P1中的坐标改成如下:
float[][][] P1={
{{-0.8f, -1.2f, -0.8f, 1.f}, {-0.2f, 0.2f, -0.5f, 1.f},
{0.2f, 0.3f, -0.5f, 1.f}, {0.8f, -1.2f, -0.8f, 1.f}},
{{-0.8f, -0.1f, -0.2f, 1.f}, {-0.2f, 0.9f, -0.2f, 1.f},
{0.2f, 0.9f, -0.2f, 1.f}, {0.8f, -0.1f, -0.2f, 1.f}},
{{-0.8f, -0.1f, 0.2f, 1.f}, {-0.2f, 0.9f, 0.2f, 1.f},
{0.2f, 0.9f, 0.2f, 1.f}, {0.8f, -0.1f, 0.2f, 1.f}},
{{-0.6f, -0.6f, 0.9f, 1.f}, {-0.2f, 0.2f, 0.5f, 1.f},
{0.2f, 0.3f, 0.5f, 1.f}, {0.6f, -0.65f, 0.8f, 1.f}}};
运行我们的代码,得到如下结果:
到这步后,我们要把最前面提到的坐标轴,与这张图相结合。这里注意一下,为了避免把自己搞混乱,运行出结果后就不要随便去转动它!!!第一印象很重要。
这就是在这张图中代表的坐标系(上下位置不一定准确)
我们的重头戏要来了,这16个点分别代表图中的哪个位置,因为这个图像凹凸有致,我们很容易想到去调整它的Y坐标,来得到最佳的观察效果。
我们将这里的坐标分别4组,从上至下,从左至右,依次记为1,2,3……16
首先我们将第一个点的Y坐标改为0,观察效果
可以看到已经有了一定的变化,随后我们转动图像,以俯视的视角,也就是想象自己飞到了图像的上方。
可以看到图形的这一角比较特别,相比较原先有点翘起,归根结底就是我们把第一个点的纵坐标由-1.2f变为了0f,产生了这个效果。有兴趣的同学可以再把它改成-1.2f,就会得到如下 结果:
我们依葫芦画瓢,把这16个点都改一遍,也就是只把它们的Y坐标改为0,分别会得到以下结果(均采用了俯视的视角):
到这里,我们第一组的坐标全部测试完毕了,相信大家一定对坐标和曲面之间的对应关系有了一定的了解。现在我们再测一下每组的第一个点,同样修改其Y坐标
自己都试一遍印象才能深刻噢!
接着我们看看把全部的Y坐标归0的结果
可以看到打开的时候已经变成了一个平面了,不再是曲面,这也给了 我们一个构造平面的思路,也就是把16个点的XYZ任意一个全部设置为0,就可以得到平面。
当然学到这里,你已经掌握了一个曲面是如何运转的,然而我们的作品肯定不是只由一个曲面就能完成,除非你看开了。
接下来我们将详细分析一下,自己如何再加一个曲面,然后在此基础上,你可以添加任意N个面
添加如下代码, 这里的P2是由P1的Y坐标修改为0.5f得来,也就是把整个面往上抬了0.5f的距离,可以先在脑海中想想会是什么样子再往下滑,建立空间感
float[][][] P2={
{{-0.8f, 0.5f, -0.8f, 1.f}, {-0.2f, 0.5f, -0.5f, 1.f},
{0.2f, 0.5f, -0.5f, 1.f}, {0.8f, 0.5f, -0.8f, 1.f}},
{{-0.8f, 0.5f, -0.2f, 1.f}, {-0.2f, 0.5f, -0.2f, 1.f},
{0.2f, 0.5f, -0.2f, 1.f}, {0.8f, 0.5f, -0.2f, 1.f}},
{{-0.8f, 0.5f, 0.2f, 1.f}, {-0.2f, 0.5f, 0.2f, 1.f},
{0.2f, 0.5f, 0.2f, 1.f}, {0.8f, 0.5f, 0.2f, 1.f}},
{{-0.6f, 0.5f, 0.9f, 1.f}, {-0.2f, 0.5f, 0.5f, 1.f},
{0.2f, 0.5f, 0.5f, 1.f}, {0.6f, 0.5f, 0.8f, 1.f}}};
//定义第一个Bezier曲面外观属性
Appearance app2 = new Appearance();
PolygonAttributes polygona2=new PolygonAttributes();
polygona2.setBackFaceNormalFlip(true);
polygona2.setCullFace(PolygonAttributes.CULL_NONE);
polygona2.setPolygonMode(PolygonAttributes.POLYGON_LINE);
app2.setPolygonAttributes(polygona2);
ColoringAttributes color2=new ColoringAttributes();
color2.setColor(0.8f,0.f,0.f);
app2.setColoringAttributes(color2);
Shape3D BezierSurfaceface2=new BezierThreeOrderSurfaceface(P2,app2);
transformgroup.addChild(BezierSurfaceface2);
说说要改的地方,P2 app2 polygona2 color2 BezierSurfaceface2
这里都由原先的1改为了2,要是想添加3个,4个,10个,100个,也是以此类推。
效果如下:
看到这里,相信你一定已经会意了
小练习:可以先动手试试如何用6个曲面拼成一个方块
本次教程就到这里了,快去完成自己的设计作品吧!
4班冲!
package com.test.demo01;
import java.applet.Applet;
import java.awt.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;
public class BezierSurfaceMerging extends Applet
{public BranchGroup createBranchGroupSceneGraph()
{BranchGroup BranchGroupRoot =new BranchGroup();
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
Color3f bgColor=new Color3f(0f,1.0f,1.0f);
Background bg=new Background(bgColor);
bg.setApplicationBounds(bounds);
BranchGroupRoot.addChild(bg);
Color3f directionalColor=new Color3f(1.f,0.f,0.f);
Vector3f vec=new Vector3f(0.f,0.f,-1.0f);
DirectionalLight directionalLight=new DirectionalLight(directionalColor,vec);
directionalLight.setInfluencingBounds(bounds);
BranchGroupRoot.addChild(directionalLight);
Transform3D tr=new Transform3D();
tr.setScale(0.85);
TransformGroup transformgroup=new TransformGroup(tr);
transformgroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
transformgroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
BranchGroupRoot.addChild(transformgroup);
MouseRotate mouserotate = new MouseRotate();
mouserotate.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mouserotate);
mouserotate.setSchedulingBounds(bounds);
MouseZoom mousezoom = new MouseZoom();
mousezoom.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mousezoom);
mousezoom.setSchedulingBounds(bounds);
MouseTranslate mousetranslate = new MouseTranslate();
mousetranslate.setTransformGroup(transformgroup);
BranchGroupRoot.addChild(mousetranslate);
mousetranslate.setSchedulingBounds(bounds);
//定义第一个Bezier曲面的16个控制顶点
float[][][] P1={
{{-0.8f, 0f, -0.8f, 1.f}, {-0.2f, 0f, -0.5f, 1.f},
{0.2f, 0f, -0.5f, 1.f}, {0.8f, 0f, -0.8f, 1.f}},
{{-0.8f, 0f, -0.2f, 1.f}, {-0.2f, 0f, -0.2f, 1.f},
{0.2f, 0f, -0.2f, 1.f}, {0.8f, 0f, -0.2f, 1.f}},
{{-0.8f, 0f, 0.2f, 1.f}, {-0.2f, 0f, 0.2f, 1.f},
{0.2f, 0f, 0.2f, 1.f}, {0.8f, 0f, 0.2f, 1.f}},
{{-0.6f, 0f, 0.9f, 1.f}, {-0.2f, 0f, 0.5f, 1.f},
{0.2f, 0f, 0.5f, 1.f}, {0.6f, 0f, 0.8f, 1.f}}};
//定义第一个Bezier曲面外观属性
Appearance app1 = new Appearance();
PolygonAttributes polygona1=new PolygonAttributes();
polygona1.setBackFaceNormalFlip(true);
polygona1.setCullFace(PolygonAttributes.CULL_NONE);
polygona1.setPolygonMode(PolygonAttributes.POLYGON_LINE);
app1.setPolygonAttributes(polygona1);
ColoringAttributes color1=new ColoringAttributes();
color1.setColor(0.8f,0.f,0.f);
app1.setColoringAttributes(color1);
float[][][] P2={
{{-0.8f, 0.5f, -0.8f, 1.f}, {-0.2f, 0.5f, -0.5f, 1.f},
{0.2f, 0.5f, -0.5f, 1.f}, {0.8f, 0.5f, -0.8f, 1.f}},
{{-0.8f, 0.5f, -0.2f, 1.f}, {-0.2f, 0.5f, -0.2f, 1.f},
{0.2f, 0.5f, -0.2f, 1.f}, {0.8f, 0.5f, -0.2f, 1.f}},
{{-0.8f, 0.5f, 0.2f, 1.f}, {-0.2f, 0.5f, 0.2f, 1.f},
{0.2f, 0.5f, 0.2f, 1.f}, {0.8f, 0.5f, 0.2f, 1.f}},
{{-0.6f, 0.5f, 0.9f, 1.f}, {-0.2f, 0.5f, 0.5f, 1.f},
{0.2f, 0.5f, 0.5f, 1.f}, {0.6f, 0.5f, 0.8f, 1.f}}};
//定义第一个Bezier曲面外观属性
Appearance app2 = new Appearance();
PolygonAttributes polygona2=new PolygonAttributes();
polygona2.setBackFaceNormalFlip(true);
polygona2.setCullFace(PolygonAttributes.CULL_NONE);
polygona2.setPolygonMode(PolygonAttributes.POLYGON_LINE);
app2.setPolygonAttributes(polygona2);
ColoringAttributes color2=new ColoringAttributes();
color2.setColor(0.8f,0.f,0.f);
app2.setColoringAttributes(color2);
Shape3D BezierSurfaceface2=new BezierThreeOrderSurfaceface(P2,app2);
transformgroup.addChild(BezierSurfaceface2);
Shape3D BezierSurfaceface1=new BezierThreeOrderSurfaceface(P1,app1);
transformgroup.addChild(BezierSurfaceface1);
BranchGroupRoot.compile();
return BranchGroupRoot;
}
public BezierSurfaceMerging()
{setLayout(new BorderLayout());
GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
Canvas3D c=new Canvas3D(gc);
add("Center",c);
BranchGroup BranchGroupScene=createBranchGroupSceneGraph();
SimpleUniverse u=new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(BranchGroupScene);
}
public static void main(String[] args)
{new MainFrame(new BezierSurfaceMerging(),400,400); }
}
class BezierThreeOrderSurfaceface extends Shape3D
{public BezierThreeOrderSurfaceface(float[][][] P,Appearance app)
{int i,j,k;
int n0;//定义对参数u、v在[0,1]区间的等分点数
float division;//参数u在[0,1]区间的等分线段长度
n0=50;division=1.f/n0;
//分别定义存放控制顶点x、y、z坐标与第四维坐标的数组
float[][] PX=new float[4][4];
float[][] PY=new float[4][4];
float[][] PZ=new float[4][4];
float[][] P4=new float[4][4];
//定义系数矩阵及其转置矩阵
float[][] M1={{1.f,0.f,0.f,0.f},
{-3.f,3.f,0.f,0.f},
{3.f,-6.f,3.f,0.f},
{-1.f,3.f,-3.f,1.f}};
float[][] M2={{1.f,-3.f,3.f,-1.f},
{0.f,3.f,-6.f,3.f},
{0.f,0.f,3.f,-3.f},
{0.f,0.f,0.f,1.f}};
//定义Bezier曲面的u、v参数分割点坐标数组
float[][][] UV=new float[n0+1][n0+1][2];
//定义U、V矩阵数组
float[][] UU=new float[1][4];
float[][] VV=new float[4][1];
//定义存放曲面上点的坐标的数组
float[][][] SurfaceXYZ=new float[n0+1][n0+1][4];
for(i=0;i<n0+1;i++)
for(j=0;j<n0+1;j++)
{ UV[i][j][0]=i*division;
UV[i][j][1]=j*division; }
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{ PX[i][j]=P[i][j][0];
PY[i][j]=P[i][j][1];
PZ[i][j]=P[i][j][2];
P4[i][j]=P[i][j][3]; }
//计算曲面上点的坐标值
for(i=0;i<n0+1;i++)
for(j=0;j<n0+1;j++)
{ UU[0][0]=1.f;
UU[0][1]=UV[i][j][0];
UU[0][2]=UV[i][j][0]*UV[i][j][0];
UU[0][3]=UV[i][j][0]*UV[i][j][0]*UV[i][j][0];
VV[0][0]=1.f;
VV[1][0]=UV[i][j][1];
VV[2][0]=UV[i][j][1]*UV[i][j][1];
VV[3][0]=UV[i][j][1]*UV[i][j][1]*UV[i][j][1];
//计算一点的x坐标
matrixm g0=new matrixm(1,4,4,UU,M1);
matrixm g1=new matrixm(1,4,4,g0.CC,PX);
matrixm g2=new matrixm(1,4,4,g1.CC,M2);
matrixm g3=new matrixm(1,4,1,g2.CC,VV);
SurfaceXYZ[i][j][0]=g3.CC[0][0];
//计算一点的y坐标
matrixm g4=new matrixm(1,4,4,UU,M1);
matrixm g5=new matrixm(1,4,4,g4.CC,PY);
matrixm g6=new matrixm(1,4,4,g5.CC,M2);
matrixm g7=new matrixm(1,4,1,g6.CC,VV);
SurfaceXYZ[i][j][1]=g7.CC[0][0];
//计算一点的z坐标
matrixm g8=new matrixm(1,4,4,UU,M1);
matrixm g9=new matrixm(1,4,4,g8.CC,PZ);
matrixm g10=new matrixm(1,4,4,g9.CC,M2);
matrixm g11=new matrixm(1,4,1,g10.CC,VV);
SurfaceXYZ[i][j][2]=g11.CC[0][0];
//计算一点的第4维坐标
matrixm g12=new matrixm(1,4,4,UU,M1);
matrixm g13=new matrixm(1,4,4,g12.CC,P4);
matrixm g14=new matrixm(1,4,4,g13.CC,M2);
matrixm g15=new matrixm(1,4,1,g14.CC,VV);
SurfaceXYZ[i][j][3]=g15.CC[0][0];
//将齐次坐标转换为三维坐标系坐标,如果第4维为1,则不用除第4维
SurfaceXYZ[i][j][0]=SurfaceXYZ[i][j][0]/SurfaceXYZ[i][j][3];
SurfaceXYZ[i][j][1]=SurfaceXYZ[i][j][1]/SurfaceXYZ[i][j][3];
SurfaceXYZ[i][j][2]=SurfaceXYZ[i][j][2]/SurfaceXYZ[i][j][3];
}
QuadArray BezierQuadsurfaceface = new QuadArray(n0*n0*4,
GeometryArray.COORDINATES|GeometryArray.NORMALS);
int c=0;//以顶点数累加的方式设置顶点的序号
for(i=0;i<n0;i++)
{for(j=0;j<n0;j++)
{//设置一个平面上的4个点
Point3f A=new Point3f(SurfaceXYZ[i][j][0],SurfaceXYZ[i][j][1],
SurfaceXYZ[i][j][2]);
Point3f B=new Point3f(SurfaceXYZ[i][j+1][0],SurfaceXYZ[i][j+1][1],
SurfaceXYZ[i][j+1][2]);
Point3f C=new Point3f(SurfaceXYZ[i+1][j+1][0],SurfaceXYZ[i+1][j+1][1],
SurfaceXYZ[i+1][j+1][2]);
Point3f D=new Point3f(SurfaceXYZ[i+1][j][0],SurfaceXYZ[i+1][j][1],
SurfaceXYZ[i+1][j][2]);
//计算由四个点形成的平面的法向量
Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
Vector3f n = new Vector3f();
n.cross(b, a);
n.normalize();
//设置点的序号
BezierQuadsurfaceface.setCoordinate(c, A);
BezierQuadsurfaceface.setCoordinate(c+1, B);
BezierQuadsurfaceface.setCoordinate(c+2, C);
BezierQuadsurfaceface.setCoordinate(c+3, D);
//设置点的法向量
BezierQuadsurfaceface.setNormal(c, n);
BezierQuadsurfaceface.setNormal(c+1, n);
BezierQuadsurfaceface.setNormal(c+2, n);
BezierQuadsurfaceface.setNormal(c+3, n);
c=c+4;
}}
this.addGeometry(BezierQuadsurfaceface);
this.setAppearance(app);
}}
class BezierSurfaceControlPoints extends Shape3D
{public BezierSurfaceControlPoints(float[][][] P,Appearance app)
{int i,j,k;
QuadArray BeziersurfacecontrolPointsNet =new QuadArray(3*3*4,
GeometryArray.COORDINATES|GeometryArray.NORMALS);
int c=0;
for(i=0;i<3;i++)
{for(j=0;j<3;j++)
{Point3f A=new Point3f(P[i][j][0],P[i][j][1],P[i][j][2]);
Point3f B=new Point3f(P[i][j+1][0],P[i][j+1][1],P[i][j+1][2]);
Point3f C=new Point3f(P[i+1][j+1][0],P[i+1][j+1][1],P[i+1][j+1][2]);
Point3f D=new Point3f(P[i+1][j][0],P[i+1][j][1],P[i+1][j][2]);
Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
Vector3f n = new Vector3f();
n.cross(b, a);
n.normalize();
BeziersurfacecontrolPointsNet.setCoordinate(c, A);
BeziersurfacecontrolPointsNet.setCoordinate(c+1, B);
BeziersurfacecontrolPointsNet.setCoordinate(c+2, C);
BeziersurfacecontrolPointsNet.setCoordinate(c+3, D);
BeziersurfacecontrolPointsNet.setNormal(c, n);
BeziersurfacecontrolPointsNet.setNormal(c+1, n);
BeziersurfacecontrolPointsNet.setNormal(c+2, n);
BeziersurfacecontrolPointsNet.setNormal(c+3, n);
c=c+4;
}}
this.addGeometry(BeziersurfacecontrolPointsNet);
this.setAppearance(app);
}}
class matrixm
{public float CC[][]= new float[4][4];
int ll,mm,kk;
public matrixm(int mmm, int kkk, int nnn,float a[][],float b[][])
{for(ll=0;ll<mmm;ll++)
for(mm=0;mm<nnn;mm++){CC[ll][mm]=0.f;}
for(ll=0;ll<mmm;ll++)
for(mm=0;mm<nnn;mm++)
{for(kk=0;kk<kkk;kk++) CC[ll][mm]=CC[ll][mm]+a[ll][kk]*b[kk][mm];}
}}