`
micheal19840929
  • 浏览: 163188 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

M3G教程:进阶篇(二)灯光

    博客分类:
  • J2ME
阅读更多

 

灯光(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

分享到:
评论

相关推荐

    M3G API Docs

    **M3G API Docs**,全称为Mobile 3D Graphics API文档,是针对移动设备上3D图形编程的一套接口规范。这套API旨在为手持设备如智能手机和平板电脑提供高效、低功耗的3D图形处理能力,使开发者能够创建出具有丰富视觉...

    M3G Viewer:查看M3G文件内容-开源

    M3G查看器是一个独立的应用程序,用于查看3D图形文件格式的内容,该格式是对移动3D图形API(M3G)的补充。

    J2ME_M3G_API.rar_M3G API_j2me 3d_j2me m_jsr 184 api c_m3g a

    **J2ME_M3G_API** 是一个与Java 2 Micro Edition(J2ME)相关的压缩包,专注于M3G(Mobile 3D Graphics)API的文档。M3G API是J2ME平台上的一个标准,它允许开发者创建在移动设备上运行的3D图形应用程序。JSR 184...

    tk_m3gtk_v4_5.zip_m3g_tk_m3g_tk_m3gtk_v4_5

    1. **M3G解析器**:这是程序的核心部分,负责读取M3G文件的二进制数据,解析出模型的几何信息、材质属性、光照设置、动画序列等,并将其转化为可以显示的结构。 2. **3D渲染引擎**:利用Java J2ME的图形库,将解析...

    M3G 的快速模式编程

    【M3G 快速模式编程】:M3G,全称Mobile 3D Graphics API,是基于JSR 184规范定义的一种为移动设备提供标准3D图形功能的API。它分为快速模式和保留模式。快速模式专注于单个3D对象的渲染,适合进行低级别的3D操作,...

    M3M0:M3m0工具:crossed_swords:网站漏洞扫描程序和自动利用程序

    M3M0渗透测试工具 M3m0工具 :crossed_swords: 网站漏洞扫描程序和自动浏览器您可以使用此工具通过在网站中找到漏洞来检查安全性,也可以使用此工具来获取Shell | 污损| cPanels | 资料库 M3M0 :laptop:M3m0工具 :...

    jsr_184_midlet.rar_DEMO_jsr184_jsr184-m3g.jar_m3g

    在提供的压缩包"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

    《Mobile 3D Graphics with OpenGL ES and M3G》是一本深入探讨移动设备上3D图形编程的专业书籍,主要关注于OpenGL ES和M3G这两个技术。OpenGL ES(OpenGL for Embedded Systems)是OpenGL的轻量级版本,专为嵌入式...

    宝箧印塔模型设计m3g

    《宝箧印塔模型设计与实现——基于Java M3G技术》 在移动设备领域,尤其是在支持Java 2 Micro Edition(J2ME)的手机上,实现三维图形渲染是一项技术挑战。本文将深入探讨如何利用Java M3G(Mobile 3D Graphics)...

    Java M3G相关类.rar

    Java M3G是Java Micro Edition (JME) 平台上用于移动设备3D图形开发的API,它基于OpenGL ES标准,使得开发者能够在手机等嵌入式设备上创建复杂的3D游戏和应用程序。这个"Java M3G相关类.rar"压缩包包含了一些关键的...

    LoaderM3G.rar_j2me loaderm_m3g_手机加载_手机游戏加载

    1. **解析M3G文件**:使用J2ME的M3G API,开发者需要编写代码来读取M3G文件的二进制数据,并将其转换为可操作的对象,如顶点、纹理坐标、索引和动画数据。 2. **初始化3D环境**:设置3D场景,创建相机、光源等元素...

    一款纯静态的M3U8播放器页面

    源码说明:一个纯静态的M3U8播放器页面,可以直接把M3U8的网址填进去进行播放,超级方便。 部署方法: 可以使用宝塔面板来部署 1,打开宝塔面板,添加一个网站 2,把压缩包上传到站点跟目录,然后解压 3,解压以后...

    联想BIOS_L-IG41M3 V1.1 版本:DMKT05AUS 新圆梦F208

    联想BIOS_L-IG41M3 V1.1 版本:DMKT05AUS 新圆梦F208 原机备份 支持Q9400 支持8G内存 需两条4G双面内存 两个BIOS文件 AFUWIN备份的BIOS BIOS_Backup_TooKit_V2.0备份的BIOS

    M3G2FBX_neko_

    "M3G2FBX_neko_" 提供了解决这一问题的解决方案,它是一款专为游戏设计的模型转换工具,主要功能是将M3G格式的模型转换为FBX格式。M3G是一种由Java 3D API支持的3D模型格式,而FBX则是Autodesk的通用3D模型交换格式...

    M3u Parser:m3u和m3u8解析器-开源

    《深入理解M3U与M3U8:解析与Java实现》 M3U和M3U8是两种广泛应用于多媒体播放的索引文件格式,主要用于组织和播放音频、视频资源。它们在流媒体服务中扮演着至关重要的角色,允许用户连续地、无需等待下载完成即可...

    M3U8Loader:M3U8装载机

    M3U8Loader是一个专为处理M3U8格式文件的工具,主要功能是加载M3U8清单并将其内容组合成一个可播放的MP4文件。M3U8是一种基于HTTP的流媒体协议,广泛应用于在线视频传输,特别是在 HLS(HTTP Live Streaming)系统中...

    m3u8资源下载

    在IT行业中,m3u8是一种常见的多媒体播放列表格式,主要应用于流媒体服务,如在线视频和音频。这种格式基于HTTP Live Streaming (HLS) 协议,由Apple公司开发,目的是实现不同网络条件下的自适应流媒体播放。m3u8...

    [JSR-184][3D编程指南]Part V: Heightmap terrain rendering using M3G

    这篇【3D编程指南】的第五部分主要探讨的是使用M3G来实现地形渲染,特别是基于高度图(Heightmap)的地形渲染技术。 首先,理解高度图的概念至关重要。高度图是一种2D图像,其中每个像素的灰度值代表一个3D网格中的...

    jsr184+M3G+API.rar

    【标题】"jsr184+M3G+API.rar" 涉及到的主要技术是Java Mobile 3D Graphics API(JSR 184)和M3G(Mobile 3D Graphics)标准,以及相关的API接口。JSR 184是Java Community Process发布的一个规范,目的是为Java ME...

    m3u8Download:java下载m3u8视频,解密并合并ts java download m3u8 video,decrypt & merge ts slice

    m3u8Dowloadjava下载m3u8视频,解密并合并tsm3u8链接获取方式以及代码分析请参见:准备JDK:1.8开发环境:IntelliJ IDEA用于解密的jar包:bcprov-jdk16-139.jar了解一些m3u8标签作用...M3u8DownloadFactory.getInstance...

Global site tag (gtag.js) - Google Analytics