- 浏览: 166297 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
兰斯洛特1987:
顶!!!!谢谢分享.最近我也在研究这玩意...
Java语言的Hook实现 -
pu02203:
我把Confidant.jar, 丢进去eclipse, 里面 ...
重磅推出诛仙辅助软件第二波:Java版按键精灵 -
泣血端午:
Calculagraph 这是哪个类啊?
A星算法 -
haitaohehe:
我使用的是jstl1.0 可是在使用<c:set va ...
JSTL1.0和JSTL1.1的区别 -
micheal19840929:
学习楼主,我也测试一下~看看兼容性吧。lanlanzhilia ...
手机版飞鸽传书:无线牵
灯光(Lighting)
java.lang.Object
+-javax.microedition.m3g.Object3D
+-javax.microedition.m3g.Transformable
+-javax.microedition.m3g.Node
+-javax.microedition.m3g.Light
在一个没有光线的房间中,所有的东西看上去都是黑的。那么前面的示例中没有光线,怎么还能看到东西呢?顶点颜色和材质是不需要光线的,它们永远显示为定义好的颜色。但光线会使它们发生一些变化,可增加景深。
光线的方向会根据对象的位置发生反射。如果您用手电筒垂直地照射您面前的镜子,那么光线会反射到您身上。如果镜子是倾斜的,则光线的入射角和反射角是完全相同的。总的来说,您需要一个与照射平面相垂直的方向向量。这一向量就称为法线向量 或简称为法线。M3G 会根据法线、光源位置和摄像机位置计算着色的情况。
此外,法线是各顶点都具备的属性,各顶点之间的像素着色既可采用插值法(PolygonMode.SHADE_SMOOTH
)也可从三角形的第三个顶点处选取(PolygonMode.SHADE_FLAT
)。由于立方体有 8 个顶点,支持法线的方法之一就是指定从立方体中心指向各角的向量,如图 7a 所示。但这样做可能会导致立方体着色不当。有三个面的颜色可能会相同,其中有些边成为不可见状态,使立方体看上去缺乏棱角。这显然更适合球体,不太适合立方体。图 7b 展示了如何为每边使用 4 条法线 —— 共 24 条,从而创建棱角分明的边线。由于一个顶点只能有一条法线,所以还要复制顶点。
图 7.带有法线向量的立方体:a) 8 条法线;b) 24 条法线(每边 4 条)
可使用法线计算光线后,还需要告诉 M3G 您需要什么类型的光线。光线来源于不同形式:灯泡、太阳、手电筒等等。在 M3G 中的对应术语分别为全向光、定向光和聚光。
- 全向光是从一个点发出的,并平均地照射各个方向。没有灯罩的灯泡发出的就是这样的光。
- 定向光向一个方向发出平行的光线。太阳离我们的距离非常远,所以可以将其光线视为平行的。定向光没有位置,只有方向。
- 手电筒或剧场中使用的聚光灯发射出的光线就是聚光。其光线呈锥形,与圆锥相交的平面上的对象会被照亮。
在真实世界中,光线还会从对象上反射回来而将周围照亮。如果您打开卧室灯,就会发现即便没有能直接照射到床底下的光线,但床下仍会被照亮。Raytracer 通过追踪从摄像机到光源的路径而清晰真实地展示了图像,但需要很长时间。要获得交互式帧频,必须满足一个简单的模型:环境光。环境光以不变的频率从各方向照亮对象。您可以用环境光模拟前面的卧室场景,将所有对象都照亮到一定程度,从而提供了另外一个全向光源。
Light.OMNI:全向光
Light.SPOT:聚光
Light.AMBIENT:环境光
Light.DIRECTIONAL:定向光
材质(Material)
An Appearance component encapsulating material attributes for lighting computations. Other attributes required for lighting are defined in Light, PolygonMode and VertexBuffer.
The diagram below illustrates how the final, lit color is obtained for a vertex. Lighting is disabled for a submesh if it has a null Material, and enabled otherwise. If lighting is disabled, the final vertex color is taken from the associated VertexBuffer as such. If lighting is enabled, the final color is computed according to the OpenGL 1.3 lighting equation (p. 48), using the material colors specified here. Finally, if vertex color tracking is enabled, the AMBIENT
and DIFFUSE
material colors are replaced with the per-vertex colors or the default color obtained from the VertexBuffer.
Lighting is computed according to the OpenGL 1.3 specification, section 2.13.1, with the following exceptions:
- the secondary color is not supported;
- the same Material is used for both the front face and the back face;
- vertex color tracking is limited to
AMBIENT_AND_DIFFUSE
; - for an ambient Light, the diffuse and specular intensities are zero;
- for a directional or positional Light, the ambient intensity is zero;
- the diffuse and specular Light intensities can not be set separately;
- the global scene ambient color acs is not supported;
Diffuse:漫反射,反射光均匀地分散到各个方向。
Ambient:环境反射,由环境光源反射的光线。
Emissive:放射光,一个像炽热的物体那样发射光线的对象。
Specular:镜面反射,光线从有光亮平面的对象反射回来。
环境反射仅对环境光起作用,因此,使用全向光是无效的。漫反射材质组件会造成一种不光滑的表面,而放射光组件则制造出一种发光效果。镜面反射颜色组件强调了发亮的效果。此外,您还可以通过使用更多的三角形改进明暗对比的着色质量。
可以使用 Material.setVertexColorTrackingEnable() 为环境反射和漫反射使用顶点颜色,不必使用Material.setColor()
转换(Transform)
本示例中使用了Transform将摄影机向后移动以便全方位观看圆环,通过同样的方式我们也可以操作任意的Object3D对象。
您可以通过数学方式将转换表示为矩阵操作。一个向量 —— 例如,摄像机位置 —— 乘以恰当的平移矩阵从而得到相应移动的向量。Transform 对象就表示了这样的一个矩阵。对于绝大多数普通转换来说,M3G 提供了 3 种便于使用的接口,隐藏了底层的数学计算:
- Transform.postScale(float sx, float sy, float sz):在 x、y、z 方向伸缩 3D 对象。大于 1 的值将按照给定因数扩大对象;0 和 1 之间的值将缩小对象。负值则同时执行伸缩和镜像操作。
- Transform.postTranslate(float tx, float ty, float tz):通过为 x、y 和 z 坐标增加指定值移动 3D 对象。负值则表示向负轴方向移动对象。
-
Transform.postRotate(float angle, float ax, float ay, float az):按给定角度绕穿过(0,0,0)和(ax,ay,az)的轴旋转对象。角度为正值,则表示若您顺着正旋转轴方向观察,对象是按顺时针旋转的。例如,
postRotate(30, 1, 0, 0)
将绕 x 轴将对象旋转 30 度。
所有操作名都是以 "post" 开头的,表示当前 Transform 对象是从右边与给定转换矩阵相乘的 —— 矩阵操作的顺序是非常重要的。如果您向右旋转 90 度,然后走两步,这时您所处的位置显然与先走两步再转身不同。您可以在各步行指令之后调用两个 post 方法 postRotate() 和 postTranslate(),从而获得上面的步行指令。调用顺序决定了所获得的步行指令。由于使用的是后乘,所以您最后使用的转换会首先应用。
M3G 有一个 Transform 类和一个 Transformable 接口。所有快速模式的 API 均可接受 Transform 对象作为参数,用于修改其关联的 3D 对象。另外,在保留模式下使用 Transformable 接口来转换作为 3D 世界一部分的节点。
A generic 4x4 floating point matrix, representing a transformation. By default, all methods dealing with Transform objects operate on arbitrary 4x4 matrices. Any exceptions to this rule are documented explicitly at the method level.
Even though arbitrary 4x4 matrices are generally allowed, using non-invertible (singular) matrices may produce undefined results or an arithmetic exception in some situations. Specifically, if the modelview matrix of an object is non-invertible, the results of normal vector transformation and fogging are undefined for that object.
import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.game.GameCanvas; import javax.microedition.m3g.Appearance; import javax.microedition.m3g.Camera; import javax.microedition.m3g.Graphics3D; import javax.microedition.m3g.IndexBuffer; import javax.microedition.m3g.Light; import javax.microedition.m3g.Material; import javax.microedition.m3g.Mesh; import javax.microedition.m3g.PolygonMode; import javax.microedition.m3g.Transform; import javax.microedition.m3g.TriangleStripArray; import javax.microedition.m3g.VertexArray; import javax.microedition.m3g.VertexBuffer; import javax.microedition.m3g.World; public class M3GCanvas extends GameCanvas implements Runnable { public static final int FPS = 20; //每秒绘制的帧数 private Graphics3D g3d; private World world; private boolean runnable=true; private Thread thread; private Mesh mesh; private Camera camera; private Light light; private Material material; protected M3GCanvas() { super(false); setFullScreenMode(true); g3d = Graphics3D.getInstance(); world = new World(); camera = new Camera(); world.addChild(camera); float w = getWidth(); float h = getHeight(); camera.setPerspective(60.0f, w / h, 0.1f, 80f); Transform cameraTransform = new Transform(); cameraTransform.postTranslate(0.0f, 15.0f, 10.0f); camera.setTransform(cameraTransform); camera.setOrientation(-10,1,0,0); mesh = createCube(); mesh.translate(0.0f, 0.0f, -50.0f); light=new Light(); nextLightMode(light); Transform lightTransform = new Transform(); lightTransform.postTranslate(0.0f, 0.0f, -4.5f); light.setOrientation(-30,1,0,0); // light.setOrientation(30,0,1,0); light.setColor(0xFFFFFF); g3d.resetLights(); g3d.addLight(light,lightTransform); world.addChild(light); world.addChild(mesh); world.setActiveCamera(camera); } public void run() { Graphics g = getGraphics(); while (runnable) { long startTime = System.currentTimeMillis(); mesh.postRotate(1.0f, 0.0f, 1.0f, 0.0f); try { // g3d.bindTarget(g); g3d.bindTarget(g, true, Graphics3D.DITHER | Graphics3D.TRUE_COLOR); g3d.render(world); } finally { g3d.releaseTarget(); } g.setColor(0xFF00FF); g.drawString("material:"+materailInfo, 10, 10, Graphics.LEFT|Graphics.TOP); g.drawString("light:"+lightInfo, 10, 30, Graphics.LEFT|Graphics.TOP); flushGraphics(); long endTime = System.currentTimeMillis(); long costTime = endTime - startTime; if(costTime<1000/FPS) { try{ Thread.sleep(1000/FPS-costTime); } catch(Exception e){ e.printStackTrace(); } } } System.out.println("Canvas stopped"); } public void start() { thread=new Thread(this); thread.start(); } public void stop() { this.runnable=false; try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } protected void keyPressed(int keyCode) { switch(keyCode) { case KEY_NUM2: nextMaterial(); break; case KEY_NUM4: nextLightMode(light); break; case KEY_NUM6: case KEY_NUM8: } } private int materialTypeIndex=0; private String materailInfo=null; private void nextMaterial() { materialTypeIndex++; materialTypeIndex=(materialTypeIndex+4)%4; switch(materialTypeIndex) { case 0: material.setColor(Material.EMISSIVE, 0x00FF0000); materailInfo="EMISSIVE"; System.out.println("use material:EMISSIVE"); break; case 1: material.setColor(Material.AMBIENT, 0x00FF0000); materailInfo="AMBIENT"; System.out.println("use material:AMBIENT"); break; case 2: material.setColor(Material.DIFFUSE, 0x00FF0000); materailInfo="DIFFUSE"; System.out.println("use material:DIFFUSE"); break; case 3: material.setColor(Material.SPECULAR, 0x00FF0000); materailInfo="SPECULAR"; System.out.println("use material:SPECULAR"); break; } } private int modeIndex=0; private String lightInfo=null; protected void nextLightMode(Light light) { modeIndex++; modeIndex=(modeIndex+4)%4; switch (modeIndex) { case 0: light.setMode(Light.AMBIENT); light.setIntensity(1.0f); lightInfo="AMBIENT"; System.out.println("use light mode:AMBIENT"); break; case 1: light.setMode(Light.DIRECTIONAL); light.setIntensity(1.0f); lightInfo="DIRECTIONAL"; System.out.println("use light mode:DIRECTIONAL"); break; case 2: light.setMode(Light.OMNI); light.setIntensity(1.0f); lightInfo="OMNI"; System.out.println("use light mode:OMNI"); break; case 3: light.setMode(Light.SPOT); light.setSpotAngle(45.0f); light.setIntensity(2.0f); lightInfo="SPOT"; System.out.println("use light mode:SPOT"); break; } } private Mesh createCube(){ short[] vert = { 10, 10, 10, -10, 10, 10, 10, -10, 10, -10, -10,10, // front -10, 10, -10, 10, 10, -10, -10, -10, -10, 10, -10, -10, // back -10, 10, 10, -10, 10, -10, -10, -10, 10, -10, -10, -10, // left 10, 10, -10, 10, 10, 10, 10, -10, -10, 10, -10, 10, // right 10, 10, -10, -10, 10, -10, 10, 10, 10, -10, 10, 10, // top 10, -10, 10, -10, -10, 10, 10, -10, -10, -10, -10, -10 }; // bottom VertexArray vertArray = new VertexArray(vert.length / 3, 3, 2); vertArray.set(0, vert.length / 3, 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 }; VertexArray normArray = new VertexArray(norm.length / 3, 3, 1); normArray.set(0, norm.length / 3, norm); int[] stripLen = { 4, 4, 4, 4, 4, 4 }; IndexBuffer indexBuffer = new TriangleStripArray(0, stripLen); VertexBuffer vertexBuffer = new VertexBuffer(); vertexBuffer.setPositions(vertArray, 1.0f, null); vertexBuffer.setNormals(normArray); Appearance cubeAppearance = new Appearance(); PolygonMode pm = new PolygonMode(); pm.setShading(PolygonMode.SHADE_SMOOTH); pm.setCulling(PolygonMode.CULL_NONE); material = new Material(); nextMaterial(); Appearance app = new Appearance(); app.setPolygonMode(pm); cubeAppearance.setMaterial(material); Mesh mesh = new Mesh(vertexBuffer, indexBuffer, cubeAppearance); return mesh; } }
运行结果如下:
本文部分内容引用自:http://dev.csdn.net/develop/article/80/80828.shtm
发表评论
-
J2ME的RMS
2010-04-10 23:32 2492在JAVAME中,程 ... -
M3G游戏中性能提升技巧
2010-03-28 17:59 736JSR184 M3G(Mobile 3D Grap ... -
在J2ME开发中获取系统属性
2010-03-27 18:21 507在J2ME开发中,我们经常需要和手机系统进行交互,获得一些和系 ... -
导出M3G文件指南
2010-03-25 12:54 940概述: 这 ... -
J2ME中使用microlog
2010-03-22 22:17 1395import javax.microedition.mi ... -
M3G教程:进阶篇(六)动画
2010-03-21 21:33 1298M3G中动画的数据结构如下: 【载入W ... -
3DS MAX导出M3G动画
2010-03-21 10:11 19821、用3D Studio Max或者Maya的插件h3texp ... -
M3G教程:进阶篇(四)模型
2010-03-21 01:18 1044import javax.microedition.lc ... -
M3G教程:进阶篇(三)纹理
2010-03-21 01:18 1014纹理(Texture) java.lang.Objec ... -
M3G教程:进阶篇(一)金字塔
2010-03-21 01:15 1196关于World public class World ... -
M3G教程:入门篇
2010-03-21 01:14 16253D技术对我们来 ... -
一点对m3g模型文件解析的工作
2010-02-11 09:49 848因为最近不会在m3g文件上继续工作,把之前一点少少的工作放出来 ... -
J2ME 3d之3DMAX制作M3G错误二例
2010-02-11 09:35 0(1) 在制作J2ME 3D所需的M3G时出现导出 ... -
M3G教程:进阶篇(五)立即模式
2010-02-09 23:51 0保留模式和立即模式渲染 保留模式是当你使用一个世界它含有的全 ... -
KVM的类加载
2010-02-09 15:46 810首先简要介绍一下class文件的结构(详细内容请参考Java虚 ... -
手机版飞鸽传书:无线牵
2010-01-30 21:02 2911【中文名】无线 ... -
FileConnection简介(JSR-75)
2010-01-29 01:17 8741 引言 本文档 ... -
J2ME添加自定义图标
2010-01-23 23:52 1354与图标有关的是这两行: MIDlet-Icon: ... -
j2me签名相关注意事项
2010-01-23 23:45 2011我们得到一个证书后就可以对j2me的jad文件进行签名。这 ... -
JAD中文名字解决方法
2010-01-12 16:44 834最近正好在弄JAD,碰到中文无法显示的问题,之前就碰到过,但没 ...
相关推荐
**M3G API Docs**,全称为Mobile 3D Graphics API文档,是针对移动设备上3D图形编程的一套接口规范。这套API旨在为手持设备如智能手机和平板电脑提供高效、低功耗的3D图形处理能力,使开发者能够创建出具有丰富视觉...
M3G查看器是一个独立的应用程序,用于查看3D图形文件格式的内容,该格式是对移动3D图形API(M3G)的补充。
**J2ME_M3G_API** 是一个与Java 2 Micro Edition(J2ME)相关的压缩包,专注于M3G(Mobile 3D Graphics)API的文档。M3G API是J2ME平台上的一个标准,它允许开发者创建在移动设备上运行的3D图形应用程序。JSR 184...
【M3G 快速模式编程】:M3G,全称Mobile 3D Graphics API,是基于JSR 184规范定义的一种为移动设备提供标准3D图形功能的API。它分为快速模式和保留模式。快速模式专注于单个3D对象的渲染,适合进行低级别的3D操作,...
1. **M3G解析器**:这是程序的核心部分,负责读取M3G文件的二进制数据,解析出模型的几何信息、材质属性、光照设置、动画序列等,并将其转化为可以显示的结构。 2. **3D渲染引擎**:利用Java J2ME的图形库,将解析...
M3M0渗透测试工具 M3m0工具 :crossed_swords: 网站漏洞扫描程序和自动浏览器您可以使用此工具通过在网站中找到漏洞来检查安全性,也可以使用此工具来获取Shell | 污损| cPanels | 资料库 M3M0 :laptop:M3m0工具 :...
在提供的压缩包"jsr_184_midlet.rar_DEMO_jsr184_jsr184-m3g.jar_m3g"中,我们可以看到与JSR 184相关的几个关键元素: 1. **DEMO**:这是一个演示程序,用于展示JSR 184技术的实际应用。通过这个DEMO,开发者或用户...
《Mobile 3D Graphics with OpenGL ES and M3G》是一本深入探讨移动设备上3D图形编程的专业书籍,主要关注于OpenGL ES和M3G这两个技术。OpenGL ES(OpenGL for Embedded Systems)是OpenGL的轻量级版本,专为嵌入式...
m3u8在线下载工具_m3u8视频在线提取工具 在数字化的时代,网络视频已经成为我们娱乐和学习的重要来源。其中,M3U8是一种广泛用于流媒体传输的文件格式,尤其在高清视频领域。然而,直接下载M3U8格式的视频并不像下载...
《宝箧印塔模型设计与实现——基于Java M3G技术》 在移动设备领域,尤其是在支持Java 2 Micro Edition(J2ME)的手机上,实现三维图形渲染是一项技术挑战。本文将深入探讨如何利用Java M3G(Mobile 3D Graphics)...
Java M3G是Java Micro Edition (JME) 平台上用于移动设备3D图形开发的API,它基于OpenGL ES标准,使得开发者能够在手机等嵌入式设备上创建复杂的3D游戏和应用程序。这个"Java M3G相关类.rar"压缩包包含了一些关键的...
1. **解析M3G文件**:使用J2ME的M3G API,开发者需要编写代码来读取M3G文件的二进制数据,并将其转换为可操作的对象,如顶点、纹理坐标、索引和动画数据。 2. **初始化3D环境**:设置3D场景,创建相机、光源等元素...
联想BIOS_L-IG41M3 V1.1 版本:DMKT05AUS 新圆梦F208 原机备份 支持Q9400 支持8G内存 需两条4G双面内存 两个BIOS文件 AFUWIN备份的BIOS BIOS_Backup_TooKit_V2.0备份的BIOS
《深入理解M3U与M3U8:解析与Java实现》 M3U和M3U8是两种广泛应用于多媒体播放的索引文件格式,主要用于组织和播放音频、视频资源。它们在流媒体服务中扮演着至关重要的角色,允许用户连续地、无需等待下载完成即可...
"M3G2FBX_neko_" 提供了解决这一问题的解决方案,它是一款专为游戏设计的模型转换工具,主要功能是将M3G格式的模型转换为FBX格式。M3G是一种由Java 3D API支持的3D模型格式,而FBX则是Autodesk的通用3D模型交换格式...
M3U8Loader是一个专为处理M3U8格式文件的工具,主要功能是加载M3U8清单并将其内容组合成一个可播放的MP4文件。M3U8是一种基于HTTP的流媒体协议,广泛应用于在线视频传输,特别是在 HLS(HTTP Live Streaming)系统中...
在IT行业中,m3u8是一种常见的多媒体播放列表格式,主要应用于流媒体服务,如在线视频和音频。这种格式基于HTTP Live Streaming (HLS) 协议,由Apple公司开发,目的是实现不同网络条件下的自适应流媒体播放。m3u8...
这篇【3D编程指南】的第五部分主要探讨的是使用M3G来实现地形渲染,特别是基于高度图(Heightmap)的地形渲染技术。 首先,理解高度图的概念至关重要。高度图是一种2D图像,其中每个像素的灰度值代表一个3D网格中的...