在Java 3D中载入外部3D模型文件.docx
- 文档编号:10689208
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:39
- 大小:27.85KB
在Java 3D中载入外部3D模型文件.docx
《在Java 3D中载入外部3D模型文件.docx》由会员分享,可在线阅读,更多相关《在Java 3D中载入外部3D模型文件.docx(39页珍藏版)》请在冰豆网上搜索。
在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文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 在Java 3D中载入外部3D模型文件 Java 载入 外部 模型 文件
![提示](https://static.bdocx.com/images/bang_tan.gif)