在Java 3D中载入外部3D模型文件.docx

上传人:b****5 文档编号:8643785 上传时间:2023-02-01 格式:DOCX 页数:32 大小:24.87KB
下载 相关 举报
在Java 3D中载入外部3D模型文件.docx_第1页
第1页 / 共32页
在Java 3D中载入外部3D模型文件.docx_第2页
第2页 / 共32页
在Java 3D中载入外部3D模型文件.docx_第3页
第3页 / 共32页
在Java 3D中载入外部3D模型文件.docx_第4页
第4页 / 共32页
在Java 3D中载入外部3D模型文件.docx_第5页
第5页 / 共32页
点击查看更多>>
下载资源
资源描述

在Java 3D中载入外部3D模型文件.docx

《在Java 3D中载入外部3D模型文件.docx》由会员分享,可在线阅读,更多相关《在Java 3D中载入外部3D模型文件.docx(32页珍藏版)》请在冰豆网上搜索。

在Java 3D中载入外部3D模型文件.docx

在Java3D中载入外部3D模型文件

在Java3D中载入外部3DJava3D虽然能支持众多的外部3D模型文件,但能支持被Java3D使用的外部模型文件仅为.obj和.lwd两种;分别对应ObjectFile类和Lw3dLoader类。

相比之下几款主流的3D建模软件都能生成.obj格式的文件,因此本文主要介绍使用ObjectFile类载入.obj文件的方法。

ObjectFile类有三个构造方法,分别为:

ObjectFile()

ObjectFile(intflags)

ObjectFile(intflags,floatradians)

其中flags为一个整型的常量参数,用于决定载入的3D模型以什么方式生成。

参数radians用于决定载入模型的可显示半径。

flags参数可在以下四个值之间任取一个或者用逻辑或("|")将几个参数组合使用。

ObjectFile.RESIZE:

忽略被载入的模型大小,直接把载入的模型放在一个范围在(1,1,1)到(-1,-1,-1)之间的立方体空间内,并把坐标原点设为(0,0,0)。

ObjectFile.REVERSE:

反转载入的外部模型,即可能看模型的后面。

ObjectFile.TRIANGULATE:

将模型的面以三角形方式显示,此参数主要便于观察模型凹凸面。

ObjectFile.STRIPIFY:

以模型文件内模型的实际情况显示,此参数也是默认参数。

当初始化了ObjectFile对象后就可以用load方法载入.obj格式的文件,如果模型中已包含了贴图和光照的话也将一起被载入。

load方法需要一个参数用于指出.obj格式文件所在的路径,load方法有多个重载方法可以使参数即可以接受String类的值也可以接受Url类的值或者从输入法流读入,如果模型载入成功将返回一个Scene类的对象,如果载入失败将抛异常。

Java3D针对load方法定义了三个异常类:

FileNotFoundException类:

表示文件未找到。

IncorrectFormatException类:

表示文件格式不正确。

ParsingErrorException类:

装载器解析文件时出错。

下面的代码用以演示如何用load方法将一个模型载入到Scene类的实例:

viewplaincopytoclipboardprint?

SceneloadScene=null;

intflag=ObjectFile.STRIPIFY;

ObjectFileobj=newObjectFile(flag);

try{

loadScene=obj.load(this.getClass().getClassLoader().getResource(filename));

}catch(FileNotFoundExceptione){

System.out.println("文件未找到或文件路径不正确");

e.printStackTrace();

}catch(IncorrectFormatExceptione){

System.out.println("文件格式不正确");

e.printStackTrace();

}catch(ParsingErrorExceptione){

System.out.println("装载器解析文件时出错");

e.printStackTrace();

}

SceneloadScene=null;

intflag=ObjectFile.STRIPIFY;

ObjectFileobj=newObjectFile(flag);

try{

loadScene=obj.load(this.getClass().getClassLoader().getResource(filename));

}catch(FileNotFoundExceptione){

System.out.println("文件未找到或文件路径不正确");

e.printStackTrace();

}catch(IncorrectFormatExceptione){

System.out.println("文件格式不正确");

e.printStackTrace();

}catch(ParsingErrorExceptione){

System.out.println("装载器解析文件时出错");

e.printStackTrace();

}

虽然至此我们已经载入了一个.obj格式文件的3D模型,但把它载入到场景后我们却模型并没有按我们想像的那么显示。

对比在3D建模工具中看到模型的样子,我们的模型被绕X轴逆时针的旋转了90度,这主要是Java3D的坐标系和大多数的3D建模工具的坐标系不同。

我们假设用户的显示器是垂直于桌面上,那么在Java3D中显示器的宽代表X轴,显示器的高代表Y轴,显示器垂直朝向用户的方法为Z轴(此方向也是Z轴的正数方向)。

而多数的建模工具使用的是世界坐标系,即将显示器的高代表Z轴。

因此我们需要在程序将模型绕X轴顺时针旋转90度,旋转轴坐标的方法是使用Transform3D类的rotX方法,相应的还有rotY和rotZ方法。

viewplaincopytoclipboardprint?

Transform3Dt3d=newTransform3D();

t3d.rotX(-Math.PI/2);

TransformGrouptg=newTransformGroup(t3d);

tg.addChild(loadScene.getSceneGroup);

Transform3Dt3d=newTransform3D();

t3d.rotX(-Math.PI/2);

TransformGrouptg=newTransformGroup(t3d);

tg.addChild(loadScene.getSceneGroup);

注意:

这里有一个容易混淆的概念,就是我们刚才的步骤是旋转的坐标系,而不是模型,模型是附加在坐标系的上,没有法被旋转。

而在刚才的步骤完成后就是将Z轴转向了上方(即显示器的高),而此时场中如还有其它的模型的话,它们的坐标未受影响,仍是Java3D的坐标系。

通常情况下我们载入的模型大小并不是我们所要的,我们必须要在场景中对模型进行缩放操作。

Java3D中对模型进行缩放需要用到Transform3D的setScale方法,方法可以接收一个double值或一个Vector3d对象的实例,当使用double值做参数时模型将在XYZ轴上使用同样的比例因子进行缩放,而Vector3d实例则可以分别为XYZ轴指定不同的比例因子,比例因子越接近0,模型就越小,当设为0时模型即小的不可见了。

t3d.setScale(0.05d);

t3d.setScale(newVector3d(0.01d,0,02d,0.03d));

好了,现在我将代码整理如下:

Gamemain.java 程序主入口

ScreenManager.java窗口框架类

LoadModelDemo.java 演示载入一个外部3D模型文件

ColourTile.java 实现一个平面用于地面中的单块地砖

CheckedFloor.java 实现场景中的地面

GameMain.java

viewplaincopytoclipboardprint?

importjava.awt.event.WindowAdapter;

importjava.awt.event.WindowEvent;

importjavax.swing.JFrame;

importjavax.swing.JOptionPane;

importjavax.swing.JPanel;

publicclassGameMain{

privatestaticintscrWidth=800;

privatestaticintscrHeight=600;

privatestaticintscrBitdepth=32;

privateJFramegameFrame;

privateJPanelgamePanel;

publicstaticvoidmain(String[]args)

{

GameMaingame=newGameMain();

}

publicGameMain()

{

ScreenManagerscreen=newScreenManager(scrWidth,scrHeight,scrBitdepth,"Java3DTest");

screen.setWindowMode();

gameFrame=screen.getFrame();

gamePanel=newLoadModelDemo(scrWidth,scrHeight);

gameFrame.add(gamePanel);

}

}

importjava.awt.event.WindowAdapter;

importjava.awt.event.WindowEvent;

importjavax.swing.JFrame;

importjavax.swing.JOptionPane;

importjavax.swing.JPanel;

 

publicclassGameMain{

privatestaticintscrWidth=800;

privatestaticintscrHeight=600;

privatestaticintscrBitdepth=32;

privateJFramegameFrame;

privateJPanelgamePanel;

publicstaticvoidmain(String[]args)

{

GameMaingame=newGameMain();

}

publicGameMain()

{

ScreenManagerscreen=newScreenManager(scrWidth,scrHeight,scrBitdepth,"Java3DTest");

screen.setWindowMode();

gameFrame=screen.getFrame();

gamePanel=newLoadModelDemo(scrWidth,scrHeight);

gameFrame.add(gamePanel);

}

}

ScreenManager.java

viewplaincopytoclipboardprint?

importjava.awt.Dimension;

importjava.awt.DisplayMode;

importjava.awt.GraphicsDevice;

importjava.awt.GraphicsEnvironment;

importjava.awt.Insets;

importjava.awt.Toolkit;

importjava.awt.event.WindowAdapter;

importjava.awt.event.WindowEvent;

importjavax.swing.JFrame;

importjavax.swing.JOptionPane;

publicclassScreenManager{

privateGraphicsDevicedevice;

privateJFrameframe;

privateStringtitle;

privatebooleanisResizable;

privatebooleanisWindowMode;

privateintscrWidth;

privateintscrHeight;

privateintscrBitdepth;

publicScreenManager(intscrWidth,intscrHeight,intscrBitdepth,Stringtitle)

{

this.scrWidth=scrWidth;

this.scrHeight=scrHeight;

this.scrBitdepth=scrBitdepth;

this.title=title;

}

publicScreenManager(Stringtitle)

{

this.title=title;

this.frame.setTitle(title);

}

publicvoidsetFullScreenMode()

{

device=GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

if(isSupportDisplayMode(scrWidth,scrHeight,scrBitdepth))

{

frame=newJFrame();

frame.setUndecorated(true);

frame.setResizable(false);

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

frame.setVisible(true);

device.setFullScreenWindow(frame);

try{

if(device.isFullScreenSupported()&&device.isDisplayChangeSupported())

device.setDisplayMode(newDisplayMode(scrWidth,scrHeight,scrBitdepth,DisplayMode.REFRESH_RATE_UNKNOWN));

}catch(IllegalArgumentExceptione)

{

e.printStackTrace();

System.exit(0);

}

}

else

{

JOptionPane.showMessageDialog(null,"不支持的显示分辨率!

","错误",JOptionPane.ERROR_MESSAGE);

System.exit(0);

}

}

privatebooleanisSupportDisplayMode(intwidth,intheight,intbitdepth)

{

DisplayMode[]modes=device.getDisplayModes();

for(DisplayModemode:

modes)

{

if(mode.getWidth()==width&&mode.getHeight()==height&&mode.getBitDepth()==bitdepth)

returntrue;

}

returnfalse;

}

publicvoidsetWindowMode()

{

frame=newJFrame();

frame.setResizable(false);//禁止窗体改变大小

frame.setPreferredSize(newDimension(scrWidth,scrHeight));

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//响应窗体的关闭事件,但不关闭窗体

frame.setVisible(true);

//侦听窗体事件并捕获窗体关闭中的事件,在用户确认后退出程序

frame.addWindowListener(newWindowAdapter(){

publicvoidwindowClosing(WindowEvente)

{

intres=JOptionPane.showConfirmDialog(null,"是否退出!

","退出",JOptionPane.YES_NO_OPTION);

if(res==JOptionPane.YES_OPTION)

closeFrame();

}

});

this.setFrametoCenter();

}

publicvoidsetFullWindowMode()

{

if(frame!

=null)

{

device=GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

DisplayModedisplayMode=device.getDisplayMode();

frame.setPreferredSize(newDimension(displayMode.getWidth(),displayMode.getHeight()));

}

}

publicintgetWidth()

{

returnscrWidth;

}

publicintgetHeight()

{

returnscrHeight;

}

publicJFramegetFrame()

{

returnframe;

}

//将窗体在显示屏幕内居中显示

publicvoidsetFrametoCenter()

{

if(device!

=null)

return;

Insetsinset=frame.getInsets();

intscrx=0;

intscry=0;

DimensionscrSize=Toolkit.getDefaultToolkit().getScreenSize();

if(scrSize.width>scrWidth)

scrx=(scrSize.width-scrWidth)/2;

if(scrSize.height>scrHeight)

scry=(scrSize.height-scrHeight)/2;

frame.setBounds(scrx-inset.left,scry-inset.top,scrWidth+inset.right+inset.left,scrHeight+inset.bottom+inset.top);

}

//关闭窗体事件

publicvoidcloseFrame()

{

frame.dispose();

System.exit(0);

}

}

importjava.awt.Dimension;

importjava.awt.DisplayMode;

importjava.awt.GraphicsDevice;

importjava.awt.GraphicsEnvironment;

importjava.awt.Insets;

importjava.awt.Toolkit;

importjava.awt.event.WindowAdapter;

importjava.awt.event.WindowEvent;

importjavax.swing.JFrame;

importjavax.swing.JOptionPane;

 

publicclassScreenManager{

privateGraphicsDevicedevice;

privateJFrameframe;

privateStringtitle;

privatebooleanisResizable;

privatebooleanisWindowMode;

privateintscrWidth;

privateintscrHeight;

privateintscrBitdepth;

publicScreenManager(intscrWidth,intscrHeight,intscrBitdepth,Stringtitle)

{

this.scrWidth=scrWidth;

this.scrHeight=scrHeight;

this.scrBitdepth=scrBitdepth;

this.title=title;

}

publicScreenManager(Stringtitle)

{

this.title=title;

this.frame.setTitle(title);

}

publicvoidsetFullScreenMode()

{

device=GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

if(isSupportDisplayMode(scrWidth,scrHeight,scrBitdepth))

{

frame=newJFrame();

frame.setUndecorated(true);

frame.setResizable(false);

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

frame.setVisible(true);

device.setFullScreenWindow(frame);

try{

if(device.isFullScreenSupported()&&device.isDisplayChangeSupported())

device.setDisplayMode(newDisplayMode(scrWidth,scrHeight,scrBitdepth,DisplayMode.REFRESH_RATE_UNKNOWN));

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 动态背景

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1