ITPub博客

首页 > Linux操作系统 > Linux操作系统 > J2ME Mobile 3D入门教程(二)(转)

J2ME Mobile 3D入门教程(二)(转)

原创 Linux操作系统 作者:jcszjswkzhou 时间:2019-04-26 19:09:05 0 删除 编辑

在这里我首先感谢大家对上一篇文章的支持,也正是有了大家的支持,我决定把我的Mobile3D学习过程拿出来和大家共享,希望大家能一起来讨论Mobile3D
在上一次的教程中我为您详细的介绍了,在Moble3D中通过及时运算建立3D图形,并且对从*.m3g文件中导入模型做了一个简单的介绍,这次我想在这里通过*.m3g文件的使用简单的介绍一下Mobile3D对动画的控制,以及对模型的一些操作。
首先我来简单的说一下m3g文件的建立,这个其实很简单,你只需要选择一种你所熟悉的3D图形制作软件,并安装对应的插件即可,在这里我使用的软件是MAYA和3DS MAX,插件使用的是H3T Export Plugin,该插件有maya和3ds max的,同时还需要下载一个软件M3G Tools kit。这些都可以从Sony Ericsson的网站上找到连接。插件的安装应该都没问题吧。插件安装完成后,就可以建立模型、设置材质帖图、设置摄影机、设置关键帧等等了,最后只要输出成H3T文件即可。然后再打开M3G Tools kit将h3t文件输出成m3g文件就可以了。在使用m3g文件之前最好用M3G Tools kit浏览一下该文件,为的是记录对应的信息,例如userid和该场景的树状结构等信息,这些都是非常重要的哦~如果你这样做了,你会发现这样导出的m3g文件中camera并没有在world树下,而是和world树是平级的。其实上一篇文章中我也说过,camera和渲染信息可以不被放在world树下,但是所有的模型信息必须被放到树下。当我们看m3g文件的时候比较重要的是看清楚world节点所在的位置,以及需要我们操作的模型的userid。
准备工作差不多了,现在来看Mobile3D吧,在上一文章中我说过m3g文件使用通过javax.microedition.m3g.Loader.load(String url)载入的,而且该方法返回的是javax.microedition.m3g.Object3D的数组,也许有人要问既然world是根节点,那么为什么不直接返回一个World呢?刚才让大家看m3g文件的结构的时候就已经说明了摄影机和动画设定等等并没有被放到World为节点的书中,而是和World节点同级的。而World节点是场景的根节点才对。那么我们如何才正确的取出World节点呢?方法有两个
1。遍历该Object3D数组,并比较每个元素的userid如果正式World节点的useid将该元素取出。
2。遍历该Object3D数组,并比较每个元素是不是World类的实例,那么既然World节点是场景的根节点,那么在该Object3D数组中也应该只有一个World类的实例对象。
第一个方法比较简单,我在这里只给出第二个方法的片断代码。(其实是一样的)
private void loadWorld(){
System.out.println("now loading...");
try{
buffer=Loader.load("/img/TmpMicroFile.m3g");
for(int i=0;i if(buffer[i] instanceof World){
world=(World)buffer[i];
return ;
}
}
}catch(Exception e){
buffer=null;
System.out.println("thorw a exception when loading");
e.printStackTrace();
}
}
然后我们设置摄影机,不同的是,这次我们从World中获得摄影机信息,获取后我们可以对其进行一些基本的设置这里不细说了。下面着重的说一下动画的部分。
在我们导入这个m3g文件时候我们其实已经有了动画的信息了,并且这些动画信息有可能是很复杂的,我测试了连杆两轴的运动可以没问题,从一些资料上看到的IK反向运动也没有问题。也许你已经着急了,怎么还不说如何控制动画的播放呢?简单的说World.animate()来更新动画信息,这个方法需要传进去一个int类型的参数,当你第一次调用该方法的时候,系统会记录下这个数值,后面每次调用的时候都会和这个数值相比较,然后系统替我们计算出动画更新到什么位置,同时该方法会返回一个int类型的参数,这个参数表示的下一次更新的一个建议的数值(是以毫秒为单位的)。我们这时就可以让调用这个方法的线程休眠这个时间,以便下以次更新动画数据。这里也许你会有疑问,我的动画明明只有几十帧,可是这里却反复的播放;这虽然是个好消息,但在有很多情况播放的长度、什么时候播放,都需要我们自己来控制怎么办?这时候我们就需要用到javax.microedition.m3g.AnimationController类了,其实每个动画中的每个可以动的模型都有自己的AnimationController对象,和模型动画一样我们可以通过World.find(int controllerID)来获得,在该类中我们可以通过setActiveInterval(int activeTime,int unactiveTime)来设定动画在该系统中播放的起始和重点时间,另外通过setPosition(int startTime,int endTime)方法控制这个动画需要播放哪一段落。很抱歉有关两个方法的时候在这次教程实例中我并没有使用,不过如果您想了解关于这两个方法的使用,我建议你看看WTK2.2的那个Demo3D中袋鼠的例子,那里面写的挺详细的。

这里呢我给出动画和绘制的代码片断吧
protected void paint(Graphics g) {

startTime= System.currentTimeMillis() - worldStartTime;
validity= world.animate((int)startTime);
perFrameTime=(int)System.currentTimeMillis();

g.setColor(0x00);
g.fillRect(0,0,getWidth(), getHeight());

g.setClip(0,0,getWidth(),getHeight());
g3d.bindTarget(g,true,Graphics3D.DITHER|Graphics3D.TRUE_COLOR);
g3d.setViewport(0,0,getWidth(),getHeight());


g3d.render(world);

g3d.releaseTarget();

framePor=(int)1000/((int)System.currentTimeMillis()-perFrameTime);

System.out.println("3D demo frame/sn:"+framePor);

if(validity < 1)
{ // The validity too small; allow a minimum of 1ms.
validity = 1;
}

if(validity == 0x7fffffff)
{ // The validity is infinite; scehdule a refresh in 1 second.
validity=1000;
}

}

public void run() {
while(isRun){
repaint();
try{
Thread.sleep(validity);
}catch(Exception e){}
}

}
这里如果你不喜欢使用线程的话,你可以换成Timer。个人喜好问题吧,我对线程比较熟悉,所以这里我使用的是线程。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-126967/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2007-08-29

  • 博文量
    2990
  • 访问量
    2205153