手机3D已经相当流行,现在将学习到的信息进行总结一下:
一般来说,M3G支持两种3D模式:立即模式(immediate mode)和保留模式(retained mode)。
怎么来获取数据文件?
Object3D[] objects = Loader.load("file.M3G"); Object3D[] objects2 = Loader.load(byteArray, offset);
他们均返回一个对象数组,即为三维动画数据。
有了这个信息,我们来寻找数据中的世界节点:
private void loadWorld() { try { Object3D[] buffer = Loader.load("/res/map.M3G"); for(int i = 0; i < buffer.length; i++) { if(buffer[i] instanceof World) { world = (World)buffer[i]; break; } } buffer = null; } catch(Exception e) { System.out.println("Loading error!"); reportException(e); } }
获取到世界节点,下边我们可以进行处理数据对象了。
获取照相机对象:
private void loadCamera() { if (world == null) return; cam = world.getActiveCamera(); Light l = new Light(); l.setMode(Light.AMBIENT); l.setIntensity(3.0f); world.addChild(l); }
注意:上放代码在世界节点增加了光照效果。另外,照相机可以与世界节点同级别,可以通过下边的代码来创建。
Camera cam = new Camera(); cam.translate(3.0f, 0.0f, 3.0f);
现在来看一下怎么处理我们获取的照相机对象:
private void moveCamera() { if (key[LEFT]) { camRot += 5.0f; } else if (key[RIGHT]) { camRot -= 5.0f; } cam.setOrientation(camRot, 0.0f, 1.0f, 0.0f); double rads = Math.toRadians(camRot); camSine = Math.sin(rads); camCosine = Math.cos(rads); if (key[UP]) { // Move forward cam.translate(-2.0f * (float) camSine, 0.0f, -2.0f * (float) camCosine); headDeg += 0.5f; cam.translate(0.0f, (float) Math.sin(headDeg) / 3.0f, 0.0f); } else if (key[DOWN]) { // Move backward cam.translate(2.0f * (float) camSine, 0.0f, 2.0f * (float) camCosine); headDeg -= 0.5f; cam.translate(0.0f, (float) Math.sin(headDeg) / 3.0f, 0.0f); } }
对于左右方向的旋转,我们使用照相机的函数(相对固定y轴):
setOrientation(f,f, f,f);
对于前后方向的移动,我们使用照相机的函数(为了效果,我们记录旋转的角度,x、y、z均变动):
translate(f, f, f);
好了,获取到了世界节点,并且可以简单的进行动画的移动处理。
如何来绘制,展现于手机上呢?
Graphics3D g3d = Graphics3D.getInstance(); g3d.bindTarget(g, true, RENDERING_HINTS); g3d.render(world);
最后不要忘记了:
g3d.releaseTarget();
好了,在建立一个运行的线程,监视移动中的画面变动。
程序结束。
整体的思路是:
我们可以通过读取一个m3g文件来获取三维数据,然后可以通过这些数据找到我们需要的信息,当然,最重要的是World数据,有了它,我们可以加入对他的处理。
因为通过World可以获取到Camera,然后通过Camera的移动来改变角度,是我们产生3D的感觉。当然你也可以加入光照、纹理、网格等信息,来达到不同的效果。
在通常的Graphics中,我们只处理二维图形,处理三维的应该使用Graphics3D,我们可以通过Graphics3D.getInstance()来获取,然后将其与World进行绑定。
思路顺了,一切OK。
参见原文 :https://developer.sonyericsson.com/site/global/techsupport/tipstrickscode/mobilejava3d/p_java3d_tutorial_part1_compliments_redikod.jsp