首先我要声明一下该文章,我已经在7月29日发布到了J2ME DEV网站上了,如果您需要转载请著名出处
3D图形技术在各个领域已经越来越多的被应用了,当然这也包括了J2ME领域。在J2ME中为我们提供了JSR184这样一个可选包,该套API
实现手机上3D图形的编程。同时也伴随着移动设备硬件的发展,现在也出现了越来越的支持该可选包的手机了,例如Sony Ericsson的
K系列、S系列等等。
正巧前一段时间我简单的学习了一下3D图形学,所以最近开始对Mobile 3D的学习,在这里把学习到的东西拿出来与大家共享,希望能对大家有所帮助,也同时希望大家能够一起来学习JSR184。
下面言规正传,首先我们来想象一下在现实生活中,我们是如何观察这个世界的。我们是通过眼睛来观察,我们生活在一个3维坐标系构成的世界。在
Mobile3D中同样的有World类让你随心所欲的构造你想要的世界,当然在这里专业些,在3D制图中我们叫它“场景”;另外还有Camera类来作
为你的眼睛,你可以来设置它的位置角度等参数,来显示出不同的图像。
在Mobile
3D中是如何实现3D图像的显示呢?首先你要建立或者载入3D模型,然后根据需要设置场景中的环境、渲染方式等一系列的参数,再后生成并设置一架摄影机并
且调整好你想要的光线,调整好你所需要的位置和角度。OK还需要什么呢?按下快门,这一步就是被叫做“渲染”一切就搞定了,这听起来似乎很简单其实也并不
难,其实这也不难。
下面我们分步骤的来讲解这些步骤:
首先说模型的建立,在Mobile
3D中和大多数的3D编程API是一样的有两种方式:1 及时运算生成;2
外部建模导入。由于外部建模导入会将环境信息同时导入,所以稍候给大家做详细的介绍,这里着重要给大家介绍“及时运算生成”的部分,这样一来有助于大家了
解Mobile 3D的工作原理
在Mobile 3D中为我们提供了VertexArray和VertexBuffer俩个类,这两个类用来保存3维模型的顶点信息。
其
中VertexArray 类用处比较多,也比较灵活,这个类最常用的用法有3个,1 保存顶点坐标信息; 2 保存法线信息; 3 保存帖图信息
。有人也许要问这一个类怎么管理3种不同的东西呢?那下面我们来分析一下该类,首先该类的构造器有3个参数:1 该实例要包括的元素的数量; 2
每个元素要包括的元素数量;
3每个子元素所占的字节数。这样一来似乎清楚很多为什么这个类能被使用到3种东西上。另外该类还有一个比较常用的方法set(int
index,int length,short[]
array0)这个方法是用来向该类的实例对象种存放数据的,第一个参数是指从第几个元素开始;第二个参数是指要设置多少个;第三个参数就是实际设置的置
了。
下面简单介绍VertexBuffer类,该类才是真正保存多边形的框架信息的类。改类通过设置顶点位置、发现、帖图信息,来建立图形。其中
setPositions(VertexBuffer v,float
s,float[]b)是用来设置顶点位置的,在这个方法中你会发现有3个参数,第一个不用说了,是顶点的坐标信息,后两个是用来做坐标偏移等操作的,操
作是这样的数学公式v’=v*s+b。还有一个setNormals(vertexBuffer
norm)方法来设置法线。还有一个非常重要的方法setTexCoords(int, VertexArray, float,
float[])这个方法中参数除第一个以外,后三个和setPositions(VertexBuffer v,float
s,float[]b)是一样的,第一个参数是开始的元素编号。这样说是不是有些抽象呢?给大家一个例子吧,好让大家理解。
short x = 20;
short y = 20;
short z = 20;
short fx = (short) -x;
short fy = (short) -y;
short fz = (short) -z;
//定点坐标
short[] vert = {x,y,z, fx,y,z, x,fy,z, fx,fy,z, //D
fx,y,fz, x,y,fz, fx,fy,fz, x,fy,fz, //C
fx,y,z, fx,y,fz, fx,fy,z, fx,fy,fz, //B
x,y,fz, x,y,z, x,fy,fz, x,fy,z, //F
x,y,fz, fx,y,fz, x,y,z, fx,y,z, //A
x,fy,z, fx,fy,z, x,fy,fz, fx,fy,fz}; //E
try{vertArray=new VertexArray(vert.length/3,3,2);
vertArray.set(0,vert.length/3,vert);
}catch(Exception e){System.out.println("vert");}
//发线
byte[] norm = { 0,0,127, 0,0,127, 0,0,127, 0,0,127,
0,0,-127, 0,0,-127, 0,0,-127, 0,0,-127,
-127,0,0, -127,0,0, -127,0,0, -127,0,0,
127,0,0, 127,0,0, 127,0,0, 127,0,0,
0,127,0, 0,127,0, 0,127,0, 0,127,0,
0,-127,0, 0,-127,0, 0,-127,0, 0,-127,0};
try{normArray=new VertexArray(norm.length/3,3,1);
normArray.set(0,norm.length/3,norm);
}catch(Exception e){System.out.println("norm");e.printStackTrace();}
//给出顶点们对应图片上的点(vert和tex数组是一一对应的)
short[] tex = { 1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1 };
try{
texArray=new VertexArray(tex.length/2,2,2);
texArray.set(0,tex.length/2,tex);
}catch(Exception e){System.out.println("tex");}
//建立正方体
vb=new VertexBuffer();
vb.setPositions(vertArray,1.0f,null);
vb.setNormals(normArray);
vb.setTexCoords(0,texArray,1.0f,null);
在
上述代码中我建立一个正方体所需要全部顶点和面的信息,但大家要注意这里并没有生成对应的模型。原因就是我们还没有设置生成模型所以的其他信息,下面我们
来看看TriangleStripArray类,该类是构成面所需要的三角面的信息类,熟悉3D制图的人都清楚构造3D图形是通过多个面构造一个3D实体
的,而三角面是比较常用的一个方法。具体内容我这里不详细说明了。
下面我们还需要设置一些环境和材质信息,这里要用到的类比较多Appearance、Texture2D、Material。前来看个例子
appearnce=new Appearance();
//创建帖图
Texture2D texture=new Texture2D(image2d);
texture.setBlendColor(Texture2D.FUNC_DECAL);
texture.setWrapping(Texture2D.WRAP_REPEAT,Texture2D.WRAP_REPEAT);
texture.setFiltering(Texture2D.FILTER_NEAREST,Texture2D.FILTER_NEAREST);
material=new Material();
material.setColor(Material.DIFFUSE, 0xFFFFFFFF);
material.setColor(Material.SPECULAR, 0xFFFFFFFF);
material.setShininess(100.0f);
appearnce.setTexture(0,texture);
appearnce.setMaterial(material);
mesh=new Mesh(vb,tsa,appearnce);
mesh.setAppearance(0,appearnce);
我
个人感觉Appearance类有些类似VertexBuffer类,同样是多种属性的持有者;在这里要强调一点,就是Appearance类的设置远远
不止上述给出的东西,还有很多的设置(例如FOG也就是雾的设置)。Texture2D是帖图类,用它来设置帖图的信息,例如帖图的方式是平铺等方式。
Material物名斯意就是指材质,这里你可是设置“反光度”、“颜色”等等信息。另外这里我还要介绍一种设置渲染参数的方法
//设置poly模式设置
PolygonMode polygonMode=new PolygonMode();
polygonMode.setShading(PolygonMode.SHADE_SMOOTH);
polygonMode.setCulling(PolygonMode.CULL_NONE);
//生成外貌
appearnce=new Appearance();
appearnce.setPolygonMode(polygonMode);
看刚刚给出的代码,似乎比上面的更简单是吧?其实在PolygonMode中已经替我们做了很多工作。该的设置很类似3D MAX中的Poly的使用。
刚才的代码中还给出了一个Mesh类,该类材质最后我们要的模型。
建立模型后,我们要建立Camera。在Camera中我在这里只简单介绍两个方法setParallel(float, float,
float, float)和setPerspective(float, float, float,
float)。我们首先来看setParallel(float, float, float,
float)该方法是设置Camera的视图方法为平视图;第一个参数是设置视角的高度,注意是高度,不是角度,因为这里是平视图;第二个参数是
Camera的宽高比例,例如我们的电视是4:3、宽银幕电影是16:9;第三、四参数分别是最近和最远渲染的范围。同样的setPerspective
是设置Camera为透视图,这种视图比较接近我们日常生活中的观察的角度,而该方法的后三个参数和setParallel的后三个参数是一样的,而第一
个参数是可是角度,这里你可不要忽视这个角度问题,这个角度是在透视图中计算投影的一个重要参数。
似乎一切都设置好了,其实不然,到目前为止我们仅仅是把我们所需要的素材都准备好了。下面我们来看看Mobile
3D的管理机制,熟悉3D制图的人都清楚大部分3D软件,3D
API都是通过树状结构来管理素材的,这样的好处是每个模型、模型组、摄像机等元素作为节点都可以设置自己的旋转轴等等属性,并可以按照自己所设定好的动
画信息进行运动。在Mobile
3D中为我们规定了该树状结构的根节点必须是World类的实例对象,其中摄影机和光线比较特殊,可以不被放置在这个树中,而是通过Graphics3D
类的对象来设置(只是可以不被放到树中,而不是必须不放到树中)。
world=new World();
//world.addChild(camera);
world.addChild(mesh);
//world.setActiveCamera(camera);
//world.addChild(light);
记得在前面我们提到过模型可以从外部文件导入,这里要介绍了,你可以通过*.m3g文件导入,导入后你就可以直接获得World的实例对象,这里有
可能包括各种模型、摄像机、灯光、环境、材质以及三角面的各种信息。也就是说通过*.m3g文件,我们可以直接获得World的实力化对象。
Object3D[] roots = Loader.load(“http://www.example.com/m3g/samples/simple.m3g”);
myWorld = (World)roots[0];
最后在我们建立这棵“参天大树”后我们终于可以绘制了,这也是最激动人心的时刻喽……^-^……前看代码 g.setClip(0,0,getWidth(),getHeight());
g.drawString("3D demo",2,100,Graphics.LEFT|Graphics.TOP);
g3d.bindTarget(g,true,Graphics3D.DITHER|Graphics3D.TRUE_COLOR);
g3d.setViewport(0,0,getWidth(),getHeight());
g3d.resetLights();
g3d.clear(background);
g3d.addLight(light,transform_light);
transForm.postRotate(angle,1,1,1);
//transForm.postTranslate(0,0,0);
transform_camera.postTranslate(0,0,0.02f);
g3d.setCamera(camera,transform_camera);
g3d.render(world,transForm);
//g3d.render(vb,tsa,appearnce,transForm);
g3d.releaseTarget();
这个简单吧~不用再说什么了吧?嘿嘿
希望上述的内容对你学习有帮助,有什么问题发邮件到我的信箱zuyingwei@hotmail.com或merlin_wei@hotmail.com,当然更欢迎大家一起来探讨Moblie 3D
作者:魏祖英 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=562
3D
图形技术在各个领域已经越来越多的被应用了,当然这也包括了J2ME领域。在J2ME中为我们提供了JSR184这样一个可选包,该套API实现手机上
3D图形的编程。同时也伴随着移动设备硬件的发展,现在也出现了越来越的支持该可选包的手机了,例如Sony Ericsson的 K系列、S系列等等。
正巧前一段时间我简单的学习了一下3D图形学,所以最近开始对Mobile 3D的学习,在这里把学习到的东西拿出来与大家共享,希望能对大家有所帮助,也同时希望大家能够一起来学习JSR184。
下面言规正传,首先我们来想象一下在现实生活中,我们是如何观察这个世界的。我们是通过眼睛来观察,我们生活在一个3维坐标系构成的世界。在
Mobile3D中同样的有World类让你随心所欲的构造你想要的世界,当然在这里专业些,在3D制图中我们叫它“场景”;另外还有Camera类来作
为你的眼睛,你可以来设置它的位置角度等参数,来显示出不同的图像。
在Mobile
3D中是如何实现3D图像的显示呢?首先你要建立或者载入3D模型,然后根据需要设置场景中的环境、渲染方式等一系列的参数,再后生成并设置一架摄影机并
且调整好你想要的光线,调整好你所需要的位置和角度。OK还需要什么呢?按下快门,这一步就是被叫做“渲染”一切就搞定了,这听起来似乎很简单其实也并不
难,其实这也不难。
下面我们分步骤的来讲解这些步骤:
首先说模型的建立,在Mobile
3D中和大多数的3D编程API是一样的有两种方式:1 及时运算生成;2
外部建模导入。由于外部建模导入会将环境信息同时导入,所以稍候给大家做详细的介绍,这里着重要给大家介绍“及时运算生成”的部分,这样一来有助于大家了
解Mobile 3D的工作原理
在Mobile 3D中为我们提供了VertexArray和VertexBuffer俩个类,这两个类用来保存3维模型的顶点信息。
其
中VertexArray 类用处比较多,也比较灵活,这个类最常用的用法有3个,1 保存顶点坐标信息; 2 保存法线信息; 3 保存帖图信息
。有人也许要问这一个类怎么管理3种不同的东西呢?那下面我们来分析一下该类,首先该类的构造器有3个参数:1 该实例要包括的元素的数量; 2
每个元素要包括的元素数量;
3每个子元素所占的字节数。这样一来似乎清楚很多为什么这个类能被使用到3种东西上。另外该类还有一个比较常用的方法set(int
index,int length,short[]
array0)这个方法是用来向该类的实例对象种存放数据的,第一个参数是指从第几个元素开始;第二个参数是指要设置多少个;第三个参数就是实际设置的置
了。
下面简单介绍VertexBuffer类,该类才是真正保存多边形的框架信息的类。改类通过设置顶点位置、发现、帖图信息,来建立图形。其中
setPositions(VertexBuffer v,float
s,float[]b)是用来设置顶点位置的,在这个方法中你会发现有3个参数,第一个不用说了,是顶点的坐标信息,后两个是用来做坐标偏移等操作的,操
作是这样的数学公式v’=v*s+b。还有一个setNormals(vertexBuffer
norm)方法来设置法线。还有一个非常重要的方法setTexCoords(int, VertexArray, float,
float[])这个方法中参数除第一个以外,后三个和setPositions(VertexBuffer v,float
s,float[]b)是一样的,第一个参数是开始的元素编号。这样说是不是有些抽象呢?给大家一个例子吧,好让大家理解。
short x = 20;
short y = 20;
short z = 20;
short fx = (short) -x;
short fy = (short) -y;
short fz = (short) -z;
//定点坐标
short[] vert = {x,y,z, fx,y,z, x,fy,z, fx,fy,z, //D
fx,y,fz, x,y,fz, fx,fy,fz, x,fy,fz, //C
fx,y,z, fx,y,fz, fx,fy,z, fx,fy,fz, //B
x,y,fz, x,y,z, x,fy,fz, x,fy,z, //F
x,y,fz, fx,y,fz, x,y,z, fx,y,z, //A
x,fy,z, fx,fy,z, x,fy,fz, fx,fy,fz}; //E
try{vertArray=new VertexArray(vert.length/3,3,2);
vertArray.set(0,vert.length/3,vert);
}catch(Exception e){System.out.println("vert");}
//发线
byte[] norm = { 0,0,127, 0,0,127, 0,0,127, 0,0,127,
0,0,-127, 0,0,-127, 0,0,-127, 0,0,-127,
-127,0,0, -127,0,0, -127,0,0, -127,0,0,
127,0,0, 127,0,0, 127,0,0, 127,0,0,
0,127,0, 0,127,0, 0,127,0, 0,127,0,
0,-127,0, 0,-127,0, 0,-127,0, 0,-127,0};
try{normArray=new VertexArray(norm.length/3,3,1);
normArray.set(0,norm.length/3,norm);
}catch(Exception e){System.out.println("norm");e.printStackTrace();}
//给出顶点们对应图片上的点(vert和tex数组是一一对应的)
short[] tex = { 1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1 };
try{
texArray=new VertexArray(tex.length/2,2,2);
texArray.set(0,tex.length/2,tex);
}catch(Exception e){System.out.println("tex");}
//建立正方体
vb=new VertexBuffer();
vb.setPositions(vertArray,1.0f,null);
vb.setNormals(normArray);
vb.setTexCoords(0,texArray,1.0f,null);
在
上述代码中我建立一个正方体所需要全部顶点和面的信息,但大家要注意这里并没有生成对应的模型。原因就是我们还没有设置生成模型所以的其他信息,下面我们
来看看TriangleStripArray类,该类是构成面所需要的三角面的信息类,熟悉3D制图的人都清楚构造3D图形是通过多个面构造一个3D实体
的,而三角面是比较常用的一个方法。具体内容我这里不详细说明了。
下面我们还需要设置一些环境和材质信息,这里要用到的类比较多Appearance、Texture2D、Material。前来看个例子
appearnce=new Appearance();
//创建帖图
Texture2D texture=new Texture2D(image2d);
texture.setBlendColor(Texture2D.FUNC_DECAL);
texture.setWrapping(Texture2D.WRAP_REPEAT,Texture2D.WRAP_REPEAT);
texture.setFiltering(Texture2D.FILTER_NEAREST,Texture2D.FILTER_NEAREST);
material=new Material();
material.setColor(Material.DIFFUSE, 0xFFFFFFFF);
material.setColor(Material.SPECULAR, 0xFFFFFFFF);
material.setShininess(100.0f);
appearnce.setTexture(0,texture);
appearnce.setMaterial(material);
mesh=new Mesh(vb,tsa,appearnce);
mesh.setAppearance(0,appearnce);
我
个人感觉Appearance类有些类似VertexBuffer类,同样是多种属性的持有者;在这里要强调一点,就是Appearance类的设置远远
不止上述给出的东西,还有很多的设置(例如FOG也就是雾的设置)。Texture2D是帖图类,用它来设置帖图的信息,例如帖图的方式是平铺等方式。
Material物名斯意就是指材质,这里你可是设置“反光度”、“颜色”等等信息。另外这里我还要介绍一种设置渲染参数的方法
//设置poly模式设置
PolygonMode polygonMode=new PolygonMode();
polygonMode.setShading(PolygonMode.SHADE_SMOOTH);
polygonMode.setCulling(PolygonMode.CULL_NONE);
//生成外貌
appearnce=new Appearance();
appearnce.setPolygonMode(polygonMode);
看刚刚给出的代码,似乎比上面的更简单是吧?其实在PolygonMode中已经替我们做了很多工作。该的设置很类似3D MAX中的Poly的使用。
刚才的代码中还给出了一个Mesh类,该类材质最后我们要的模型。
建
立模型后,我们要建立Camera。在Camera中我在这里只简单介绍两个方法setParallel(float, float, float,
float)和setPerspective(float, float, float,
float)。我们首先来看setParallel(float, float, float,
float)该方法是设置Camera的视图方法为平视图;第一个参数是设置视角的高度,注意是高度,不是角度,因为这里是平视图;第二个参数是
Camera的宽高比例,例如我们的电视是4:3、宽银幕电影是16:9;第三、四参数分别是最近和最远渲染的范围。同样的setPerspective
是设置Camera为透视图,这种视图比较接近我们日常生活中的观察的角度,而该方法的后三个参数和setParallel的后三个参数是一样的,而第一
个参数是可是角度,这里你可不要忽视这个角度问题,这个角度是在透视图中计算投影的一个重要参数。
似乎一切都设置好了,其
实不然,到目前为止我们仅仅是把我们所需要的素材都准备好了。下面我们来看看Mobile
3D的管理机制,熟悉3D制图的人都清楚大部分3D软件,3D
API都是通过树状结构来管理素材的,这样的好处是每个模型、模型组、摄像机等元素作为节点都可以设置自己的旋转轴等等属性,并可以按照自己所设定好的动
画信息进行运动。在Mobile
3D中为我们规定了该树状结构的根节点必须是World类的实例对象,其中摄影机和光线比较特殊,可以不被放置在这个树中,而是通过Graphics3D
类的对象来设置(只是可以不被放到树中,而不是必须不放到树中)。
world=new World();
//world.addChild(camera);
world.addChild(mesh);
//world.setActiveCamera(camera);
//world.addChild(light);
记
得在前面我们提到过模型可以从外部文件导入,这里要介绍了,你可以通过*.m3g文件导入,导入后你就可以直接获得World的实例对象,这里有可能包括
各种模型、摄像机、灯光、环境、材质以及三角面的各种信息。也就是说通过*.m3g文件,我们可以直接获得World的实力化对象。
Object3D[] roots = Loader.load(“http://www.example.com/m3g/samples/simple.m3g”);
myWorld = (World)roots[0];
最后在我们建立这棵“参天大树”后我们终于可以绘制了,这也是最激动人心的时刻喽……^-^……前看代码 g.setClip(0,0,getWidth(),getHeight());
g.drawString("3D demo",2,100,Graphics.LEFT|Graphics.TOP);
g3d.bindTarget(g,true,Graphics3D.DITHER|Graphics3D.TRUE_COLOR);
g3d.setViewport(0,0,getWidth(),getHeight());
g3d.resetLights();
g3d.clear(background);
g3d.addLight(light,transform_light);
transForm.postRotate(angle,1,1,1);
//transForm.postTranslate(0,0,0);
transform_camera.postTranslate(0,0,0.02f);
g3d.setCamera(camera,transform_camera);
g3d.render(world,transForm);
//g3d.render(vb,tsa,appearnce,transForm);
g3d.releaseTarget();
这个简单吧~不用再说什么了吧?嘿嘿
希望上述的内容对你学习有帮助,有什么问题发邮件到我的信箱zuyingwei@hotmail.com或merlin_wei@hotmail.com,当然更欢迎大家一起来探讨Moblie 3D
PS:最后把全部代码给大家吧~别嫌我罗嗦,还有一点要强调一下的,帖图的长宽都要为2的指数例如我这里用到的帖图是64*64的
Mobile3D入门代码