java 加载3d模型_实现在Java 3D中载入外部3D模型文件方法详解
Java 3D虽然能支持众多的外部3D模型文件,但能支持被Java 3D使用的外部模型文件仅为.obj和.lwd两种;分别对应ObjectFile类和Lw3dLoader类。相比之下几款主流的3D建模软件都能生成.obj格式的文件,因此本文主要介绍使用ObjectFile类载入.obj文件的方法。
ObjectFile类有三个构造方法,分别为:
ObjectFile()
ObjectFile(int flags)
ObjectFile(int flags, float radians)
其中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类的对象,如果载入失败将抛异常。Java 3D针对load方法定义了三个异常类:
FileNotFoundException类:表示文件未找到。
IncorrectFormatException类:表示文件格式不正确。
ParsingErrorException类:装载器解析文件时出错。
下面的代码用以演示如何用load方法将一个模型载入到Scene类的实例:
view plaincopy to clipboardprint?
01.Scene loadScene = null;
02.int flag = ObjectFile.STRIPIFY;
03.ObjectFile obj = new ObjectFile(flag);
04.try {
05. loadScene = obj.load(this.getClass().getClassLoader().getResource(filename));
06.} catch (FileNotFoundException e) {
07. System.out.println("文件未找到或文件路径不正确");
08. e.printStackTrace();
09.} catch (IncorrectFormatException e) {
10. System.out.println("文件格式不正确");
11. e.printStackTrace();
12.} catch (ParsingErrorException e) {
13. System.out.println("装载器解析文件时出错");
14. e.printStackTrace();
15.}
虽然至此我们已经载入了一个.obj格式文件的3D模型,但把它载入到场景后我们却模型并没有按我们想像的那么显示。对比在3D建模工具中看到模型的样子,我们的模型被绕X轴逆时针的旋转了90度,这主要是Java 3D的坐标系和大多数的3D建模工具的坐标系不同。我们假设用户的显示器是垂直于桌面上,那么在Java 3D中显示器的宽代表X轴,显示器的高代表Y轴,显示器垂直朝向用户的方法为Z轴(此方向也是Z轴的正数方向)。而多数的建模工具使用的是世界坐标系,即将显示器的高代表Z轴。
因此我们需要在程序将模型绕X轴顺时针旋转90度,旋转轴坐标的方法是使用Transform3D类的rotX方法,相应的还有rotY和rotZ方法。
view plaincopy to clipboardprint?
01.Transform3D t3d = new Transform3D();
02.t3d.rotX(-Math.PI/2);
03.TransformGroup tg = new TransformGroup(t3d);
04.tg.addChild(loadScene.getSceneGroup);
注意:这里有一个容易混淆的概念,就是我们刚才的步骤是旋转的坐标系,而不是模型,模型是附加在坐标系的上,没有法被旋转。而在刚才的步骤完成后就是将Z轴转向了上方(即显示器的高),而此时场中如还有其它的模型的话,它们的坐标未受影响,仍是Java 3D的坐标系。
通常情况下我们载入的模型大小并不是我们所要的,我们必须要在场景中对模型进行缩放操作。Java 3D中对模型进行缩放需要用到Transform3D的setScale方法,方法可以接收一个double值或一个Vector3d对象的实例,当使用double值做参数时模型将在XYZ轴上使用同样的比例因子进行缩放,而Vector3d实例则可以分别为XYZ轴指定不同的比例因子,比例因子越接近0,模型就越小,当设为0时模型即小的不可见了。
t3d.setScale(0.05d);
或
t3d.setScale(new Vector3d(0.01d,0,02d,0.03d));
好了,现在我将代码整理如下:
Gamemain.java 程序主入口
ScreenManager.java 窗口框架类
LoadModelDemo.java 演示载入一个外部3D模型文件
ColourTile.java 实现一个平面用于地面中的单块地砖
CheckedFloor.java 实现场景中的地面
GameMain.java
view plaincopy to clipboardprint?
01.import java.awt.event.WindowAdapter;
02.import java.awt.event.WindowEvent;
03.
04.import javax.swing.JFrame;
05.import javax.swing.JOptionPane;
06.import javax.swing.JPanel;
07.
08.
09.public class GameMain {
10. private static int scrWidth = 800;
11. private static int scrHeight = 600;
12. private static int scrBitdepth = 32;
13. private JFrame gameFrame;
14. private JPanel gamePanel;
15.
16. public static void main(String[] args)
17. {
18. GameMain game = new GameMain();
19. }
20.
21. public GameMain()
22. {
23. ScreenManager screen = new ScreenManager(scrWidth,scrHeight,scrBitdepth,"Java 3D Test");
24. screen.setWindowMode();
25. gameFrame = screen.getFrame();
26. gamePanel = new LoadModelDemo(scrWidth,scrHeight);
27. gameFrame.add(gamePanel);
28. }
29.
30.}
ScreenManager.java
view plaincopy to clipboardprint?
01.import java.awt.Dimension;
02.import java.awt.DisplayMode;
03.import java.awt.GraphicsDevice;
04.import java.awt.GraphicsEnvironment;
05.import java.awt.Insets;
06.import java.awt.Toolkit;
07.import java.awt.event.WindowAdapter;
08.import java.awt.event.WindowEvent;
09.
10.import javax.swing.JFrame;
11.import javax.swing.JOptionPane;
12.
13.
14.public class ScreenManager {
15.
16. private GraphicsDevice device;
17. private JFrame frame;
18. private String title;
19. private boolean isResizable;
20. private boolean isWindowMode;
21. private int scrWidth;
22. private int scrHeight;
23. private int scrBitdepth;
24.
25. public ScreenManager(int scrWidth,int scrHeight,int scrBitdepth,String title)
26. {
27. this.scrWidth = scrWidth;
28. this.scrHeight = scrHeight;
29. this.scrBitdepth = scrBitdepth;
30. this.title = title;
31. }
32.
33. public ScreenManager(String title)
34. {
35. this.title = title;
36. this.frame.setTitle(title);
37. }
38.
39. public void setFullScreenMode()
40. {
41. device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
42. if(isSupportDisplayMode(scrWidth,scrHeight,scrBitdepth))
43. {
44. frame = new JFrame();
45. frame.setUndecorated(true);
46. frame.setResizable(false);
47. frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
48. frame.setVisible(true);
49. device.setFullScreenWindow(frame);
50. try{
51. if(device.isFullScreenSupported()&&device.isDisplayChangeSupported())
52. device.setDisplayMode(new DisplayMode(scrWidth, scrHeight, scrBitdepth, DisplayMode.REFRESH_RATE_UNKNOWN));
53. }catch(IllegalArgumentException e)
54. {
55. e.printStackTrace();
56. System.exit(0);
57. }
58. }
59. else
60. {
61. JOptionPane.showMessageDialog(null, "不支持的显示分辨率!","错误",JOptionPane.ERROR_MESSAGE);
62. System.exit(0);
63. }
64. }
65.
66. private boolean isSupportDisplayMode(int width,int height,int bitdepth)
67. {
68. DisplayMode[] modes = device.getDisplayModes();
69. for(DisplayMode mode : modes)
70. {
71. if(mode.getWidth()==width && mode.getHeight()==height && mode.getBitDepth()==bitdepth)
72. return true;
73. }
74. return false;
75. }
java 加载3d模型_实现在Java 3D中载入外部3D模型文件方法详解相关推荐
- java n%9==0_用C++实现求N!中末尾0的个数的方法详解
题目描述: 输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2 输入描述: 输入为1行,n(1≤n≤1000) 输出描述: 输出一个整数 ...
- java读写json格式的文件方法详解.txt,并批量存储进redis
捐躯赴国难,视死忽如归.恸哭六军俱缟素,冲冠一怒为红颜.君子坦荡荡,小人长戚戚.风日晴和人意好,夕阳箫鼓几船归.民为贵,社稷次之,君为轻.Java 读写json格式的文件方法详解 文章录入:7747. ...
- java加载一个来自项目之外的java文件,执行其main方法的一种实现方式
目录 写在前面 代码实现思路 代码具体实现 写在前面 近期有一个小想法,就是我一个springboot项目,想做一个给用户可以编写java代码并且直接在页面运行的功能. 难点就在于,如何将java文本 ...
- web高德地图怎么加载离线地图_基于 QGIS 在内网中离线加载卫星地图的方法
1. 概述 我们之前为大家分享过在三维地球开源平台离线加载卫星影像的方法,主要包括基于桌面端的OsgEarth开源三维地球和基于Web端的Cesium开源三维地球等平台的局域网离线影像加载. 另外,也 ...
- java加载dll UnsatisfiedLinkError: no mydll in java.library.path
System.loadLibrary("mydll"); 运行异常:java.lang.UnsatisfiedLinkError: no mydll in java.library ...
- JAVA启动杀怒尖塔_杀戮尖塔如何修改class 杀戮尖塔修改class文件方法步骤图解
杀戮尖塔如何修改class?相信小伙伴们一定很好奇,修改class文件可以在游戏中得到想要的状态,下面小编为大家带来了杀戮尖塔修改class文件方法步骤图解,感兴趣的小伙伴赶紧跟着小编一起来看看吧. ...
- 怎么运行java class_运行java的class文件方法详解
一.运行class文件 执行带main方法的class文件,命令行为: java 注意:CLASS文件名不要带文件后缀.class 例如: 复制代码代码如下: java Test 如果执行的class ...
- java判断是否闰年_java中判断是否是闰年的方法详解
给定一个年份,判断是否是闰年.条件为:(推荐:java视频教程) A:能被4整除,并且不能被100整除.或者 B:能被400整除. 分析: 首先题目中的A与B为两个判断闰年为真的选项,且属于" ...
- python中的浮点数用法_如何利用Python在运算后得到浮点数值的方法详解
在python中进行两个整数相除的时候,在默认情况下都是只能够得到整数的值,而在需要进行对除所得的结果进行精确地求值时,想在运算后即得到浮点值,那么如何进行处理呢? 1.修改被除数的值为带小数点的形式 ...
- java join yield_Java多线程中join、yield、sleep方法详解
在Java多线程编程中,Thread类是其中一个核心和关键的角色.因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础.本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的 ...
最新文章
- yum 安装指定版本php,怎样通过yum安装指定版本的php
- IDEA界面太丑??尝试一下这几个插件!
- 初次使用Shiro进行加密密码的算法实例
- 华为RH2288V3服务器部署指南
- 介绍一个好用的能让网页变成黑色背景的护眼 Chrome 扩展应用 - Night Eye
- 微服务--分布式事务的实现方法及替代方案
- HUE WorkFlow Schedule 调用Hive参数传递,外部参数传递,时间参数传递
- 如果表不存在则创建_当创建一个文件的时候,操作系统发生了什么
- jeecg公开课今晚主题:新版本功能介绍、online原理和代码生成器,欢迎大家报名
- 动态规划 343,279,91,62,63,198
- 区块链NFT项目策划书
- 我的世界服务器无限矿区块指令,我的世界区块刷新指令 | 手游网游页游攻略大全...
- 名编辑电子杂志大师教程 | 菜单设置
- 用.bat文件切换固定IP地址和自动IP地址
- go-excel文档
- 领导说“辛苦了”,千万别回“应该的”, 这是我听过最扎心的答案了!
- 祝愿大家未来顺利平安
- Word论文写作公式居中、编号右对齐设置
- html hr代码的效果,HTML hr是什么意思
- 7-38 实验7_3_奇数偶数 (100 分)奇数偶数排序
热门文章
- 服务器装系统出现命令提示符,怎么通过cmd命令提示符重装系统?具体怎么操作?...
- android的wifi开发码源,亚美电游app下载 -官方网站
- 【LaTeX应用】latex排版中插入参考文献
- 解放你的双手,python在excel中的高效办公
- Ubuntu设置自动登录
- android 锁屏_DashClock是Android的锁屏小部件应具备的功能
- Doxygen、hhc生成chm格式文档
- 一、安装 1、kafka 需要java环境;(百度网盘地址:https://pan.baidu.com/s/1i3YXtiBH9YYvZn9vQy1g8w 提取码:dot8)
- 虚拟机如何使用计算机中文件,如何从电脑往虚拟机复制文件
- 显卡天梯图2021年9月新版