上一篇给场景载入人物模型。那么如何让他在场景中移动起来呢?我们通过Transform3D类来修改对象在场景中的位置,通过监听键盘按键来改变对象的坐标。
源代码如下:
main类
1 package com.zzl.j3d.viewer;
2
3 import com.sun.j3d.utils.applet.MainFrame;
4 import com.zzl.j3d.loader.KeyInputHandler;
5
6 public class test {
7
8 public static void main(String[] args) {
9
10 Render render = new Render();
11 KeyInputHandler kih = new KeyInputHandler(render);
12
13 new MainFrame(render,400,600);
14 }
15
16 }
场景渲染类:
1 package com.zzl.j3d.viewer;
2
3 import java.applet.Applet;
4 import java.awt.BorderLayout;
5 import java.awt.GraphicsConfiguration;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.KeyEvent;
8 import java.net.URL;
9 import java.util.Arrays;
10
11 import javax.media.j3d.Appearance;
12 import javax.media.j3d.BoundingSphere;
13 import javax.media.j3d.BranchGroup;
14 import javax.media.j3d.Canvas3D;
15 import javax.media.j3d.Group;
16 import javax.media.j3d.Texture;
17 import javax.media.j3d.TextureAttributes;
18 import javax.media.j3d.Transform3D;
19 import javax.media.j3d.TransformGroup;
20 import javax.swing.Timer;
21 import javax.vecmath.Point3d;
22 import javax.vecmath.Quat4f;
23 import javax.vecmath.Vector3d;
24 import javax.vecmath.Vector3f;
25
26 import com.sun.j3d.loaders.Scene;
27 import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
28 import com.sun.j3d.utils.geometry.Box;
29 import com.sun.j3d.utils.geometry.Primitive;
30 import com.sun.j3d.utils.image.TextureLoader;
31 import com.sun.j3d.utils.universe.SimpleUniverse;
32 import com.sun.j3d.utils.universe.ViewingPlatform;
33 import com.zzl.j3d.loader.J3DLoader;
34 import com.zzl.j3d.loader.KeyInputHandler;
35
36 public class Render extends Applet {
37 private final float PI_180 = (float) (Math.PI / 180.0);
38
39 private SimpleUniverse universe ;
40 private Canvas3D canvas;
41 private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0);
42 private Transform3D tans = new Transform3D();
43 private TransformGroup objTransG = null;
44 private Timer timer = null;
45
46 private float walkbias = 0;
47 private float walkbiasangle = 0;
48 private float heading;
49
50 private float xloc = 0f;
51 private float yloc = 0f;
52 private float zloc = 0f;
53
54 private float yrot; // Y Rotation
55
56 /**
57 * 创建场景
58 */
59 public Render()
60 {
61 setLayout(new BorderLayout());
62 GraphicsConfiguration gc = SimpleUniverse.getPreferredConfiguration();
63 canvas = new Canvas3D(gc);
64 add("Center",canvas);
65
66 universe = new SimpleUniverse(canvas);
67
68 setupView();
69
70 J3DLoader loader = new J3DLoader();
71 BranchGroup objRoot = new BranchGroup();
72
73 URL texImage = loader.loadTexture("resource/flooring.jpg");
74 Group group = this.createSceneBackGround(texImage);
75
76 objTransG = new TransformGroup();
77 objTransG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
78 Transform3D pos0 = new Transform3D();
79 pos0.setTranslation(new Vector3f(0f,-1.1f,0f));
80 objTransG.setTransform(pos0);
81 objTransG.addChild(group);
82 objRoot.addChild(objTransG);
83
84 // 载入人物模型
85 Scene scene = loader.loadObj("Liit.obj");
86
87 Transform3D pos1 = new Transform3D();
88 pos1.setTranslation(new Vector3f(0f,0.0f,0f));
89 // 该 人物模型载入时默认为平行y=0平面,所以要绕x轴旋转90度
90 pos1.rotX(Math.toRadians(-90));
91
92 objTransG = new TransformGroup();
93
94 objTransG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
95 objTransG.setTransform(pos1);
96
97 objTransG.addChild(scene.getSceneGroup());
98
99 objRoot.addChild(objTransG);
100
101 universe.addBranchGraph(objRoot);
102 }
103
104 /**
105 * 建立鼠标控制的视点
106 */
107 public void setupView()
108 {
109 /** Add some view related things to view branch side of scene graph */
110 // add mouse interaction to the ViewingPlatform
111 OrbitBehavior orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL|OrbitBehavior.STOP_ZOOM);
112 orbit.setSchedulingBounds(bounds);
113 ViewingPlatform viewingPlatform = universe.getViewingPlatform();
114 // This will move the ViewPlatform back a bit so the
115 // objects in the scene can be viewed.
116 viewingPlatform.setNominalViewingTransform();
117 viewingPlatform.setViewPlatformBehavior(orbit);
118 }
119
120 public void init()
121 {
122 }
123
124 public void destroy()
125 {
126 universe.removeAllLocales();
127 }
128
129 /**
130 * 绘制一个地板
131 * @param texImage
132 * @return
133 */
134 public Group createSceneBackGround(URL texImage)
135 {
136 return createGeometry(Texture.MULTI_LEVEL_POINT , -0.0f, texImage);
137 }
138
139 public Group createGeometry(int filter, float y, URL texImage)
140 {
141 Group topNode = new Group();
142 Appearance appearance = new Appearance();
143 TextureLoader tex = new TextureLoader(texImage, TextureLoader.GENERATE_MIPMAP , this);
144 Texture texture = tex.getTexture();
145
146 texture.setMinFilter(filter);
147 appearance.setTexture(texture);
148 TextureAttributes texAttr = new TextureAttributes();
149 texAttr.setTextureMode(TextureAttributes.MODULATE);
150 appearance.setTextureAttributes(texAttr);
151
152 Transform3D pos2 = new Transform3D();
153 pos2.setTranslation(new Vector3f(0f,y,0f));
154 objTransG = new TransformGroup();
155 objTransG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
156 objTransG.setTransform(pos2);
157
158
159 Box box = new Box(6f,0.1f,8f,Primitive.GENERATE_NORMALS|Primitive.GENERATE_TEXTURE_COORDS,appearance);
160 objTransG.addChild(box);
161 topNode.addChild(objTransG);
162 return topNode;
163 }
164
165 /**
166 * 键盘被按下时调用
167 */
168 public void processKeyEvent(KeyEvent e)
169 {
170 if(!timer.isRunning())
171 timer.start();
172
173 if(e.getKeyChar()=='w')
174 {
175 xloc += (float) Math.sin(heading * PI_180) * 0.05f;
176 zloc += (float) Math.cos(heading * PI_180) * 0.05f;
177 if (walkbiasangle <= 1.0f) {
178 walkbiasangle = 359.0f;
179 } else {
180 walkbiasangle -= 10;
181 }
182 walkbias = (float) Math.sin(walkbiasangle * PI_180) / 20.0f;
183 }
184 if(e.getKeyChar()=='s')
185 {
186 xloc -= (float) Math.sin(heading * PI_180) * 0.05f;
187 zloc -= (float) Math.cos(heading * PI_180) * 0.05f;
188 if (walkbiasangle >= 359.0f) {
189 walkbiasangle = 0.0f;
190 } else {
191 walkbiasangle += 10;
192 }
193 walkbias = (float) Math.sin(walkbiasangle * PI_180) / 20.0f;
194 }
195 if (e.getKeyChar()=='d') {
196 xloc -= 0.05f;
197 }
198
199 if (e.getKeyChar()=='a') {
200 xloc += 0.05f;
201 }
202 }
203
204 public void processAction(ActionEvent e)
205 {
206 if(!timer.isRunning())
207 timer.start();
208
209 tans.setRotation(new Quat4f(1f,0f,0f,-1.0f));
210 float xtrans = -xloc;
211 float ztrans = -zloc;
212 float ytrans = -walkbias;
213 float sceneroty = 360.0f - yrot;
214
215 tans.setTranslation(new Vector3d(xtrans, ytrans, ztrans));
216 objTransG.setTransform(tans);
217 }
218
219 /**
220 * 添加监听器
221 * @param kih
222 */
223 public void registerAction(KeyInputHandler kih)
224 {
225 canvas.addKeyListener(kih);
226
227 timer = new Timer(100,kih);
228 }
229 }
230
键盘监听类:
1 /**
2 * 键盘处理类
3 */
4 package com.zzl.j3d.loader;
5
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.awt.event.KeyAdapter;
9 import java.awt.event.KeyEvent;
10
11 import com.zzl.j3d.viewer.Render;
12
13 public class KeyInputHandler extends KeyAdapter implements ActionListener{
14 private Render render;
15
16 /**
17 * 键盘处理类。注册键盘监听器
18 * @param render
19 */
20 public KeyInputHandler(Render render)
21 {
22 this.render = render;
23 render.registerAction(this);
24 }
25
26 /**
27 * 按键被按下时调用
28 * @param e
29 */
30 public void keyPressed(KeyEvent e)
31 {
32 processKeyEvent(e,true);
33 }
34 /**
35 * 按键被放开时调用
36 * @param e
37 */
38 public void keyReleased(KeyEvent e)
39 {
40
41 }
42 /**
43 * 按一个键时调用
44 * @param e
45 */
46 public void keyTyped(KeyEvent e)
47 {
48
49 }
50
51 @Override
52 public void actionPerformed(ActionEvent e) {
53 render.processAction(e);
54 }
55
56 /**
57 * 键盘被按下时处理的事件
58 * @param e
59 * @param pressed
60 */
61 private void processKeyEvent(KeyEvent e, boolean pressed)
62 {
63 render.processKeyEvent(e);
64 }
65 }
模型载入类:
1 package com.zzl.j3d.loader;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7
8 import com.sun.j3d.loaders.IncorrectFormatException;
9 import com.sun.j3d.loaders.ParsingErrorException;
10 import com.sun.j3d.loaders.Scene;
11 import com.sun.j3d.loaders.objectfile.ObjectFile;
12
13 public class J3DLoader {
14
15 private static java.net.URL texImage = null;
16
17 /**
18 * 载入obj模型
19 * @param arg0 String 模型文件名
20 * @return Scene
21 */
22 public Scene loadObj(String arg0)
23 {
24 int flags = ObjectFile.RESIZE;
25 ObjectFile f = new ObjectFile(flags,(float)(49.0 * Math.PI / 180.0));
26 // 创建场景叶节点
27 Scene s = null;
28 try {
29 s = f.load(arg0);
30 } catch (FileNotFoundException e) {
31 // TODO Auto-generated catch block
32 e.printStackTrace();
33 } catch (IncorrectFormatException e) {
34 // TODO Auto-generated catch block
35 e.printStackTrace();
36 } catch (ParsingErrorException e) {
37 // TODO Auto-generated catch block
38 e.printStackTrace();
39 }
40 return s;
41 }
42
43 /**
44 * 载入纹理图片
45 * @param args String 图片文件名
46 * @return URL
47 */
48 public URL loadTexture(String args)
49 {
50 File f = new File(args);
51 try {
52 texImage = f.toURL();
53 } catch (MalformedURLException e) {
54 // TODO Auto-generated catch block
55 e.printStackTrace();
56 }
57 return texImage;
58 }
59 }
60