本文源地址: http://blog.csdn.net/xiaominghimi/archive/2010/12/07/6059650.aspx
Himi 原创, 转载请注明! 谢谢。
为什么要先构造一个立方体的例子,其实在论证概念时,立方体是一种极好的示例,当然它并不是复杂的 3D 设计的里程碑。
首先介绍构造一个3D立方体需要的步骤:(大概步骤哦)
第一:构造一个立方体的空间顶点
第二:构造一个立方体的各个面这里会用到三角形带 ,详细三角形带的解释看 @备注1
第三:构造一个摄像机
第四:绑定画笔
第五:渲染.
那么下面先上代码,都有注释的,相信都能看懂!一些备注 下文有解释!
package com.javame;
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.Transform;
import javax.microedition.m3g.TriangleStripArray;
import javax.microedition.m3g.VertexArray;
import javax.microedition.m3g.VertexBuffer;
import com.fengchi.game.util.AbsCanvas;
/**
*
* @author Himi
*
*/
public class My3DWorld extends GameCanvas implements Runnable {
private Thread th;
/**
* @author Himi
*
* @VERTEX_POSITIONS 以三角形带形式定义一个装入了立方体所有的顶点数组
*
* @VERTEX_COLORS 以三角形带形式定义了颜色数组
*
* @TRIANGLE_INDICES 以三角形带形式装入了立方体的所有面
*
* @VertexArray 此类作用: 虽然VERTEX_POSITIONS 定义了顶点数组但是不是空间的点,
* 所以此类将顶点数组保存成空间顶点坐标信息、保存法线信息、
* 保存帖图信息、保存 颜色信息等
*
* @VertexBuffer 此类对象通过保存设置空间顶点位置、发现、帖图信息,来建立图形
* (这个类才是保存多边形的框架信息的类) 设定顶点属性
* ,包括的位置,法线,色彩,纹理坐标
*
* @Transform 对立方体进行一系列操作,例如反转 、平移、缩放
*
* @Camera 3d空间中的摄像机 设置投影、观察视角等
*
* @TriangleStripArray 此类按三角形带方式将面串成立方体
*/
private static final byte[] VERTEX_POSITIONS = { -1, -1, 1, 1, -1, 1, -1,
1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1 };
// @备注1
private static final byte[] VERTEX_COLORS = { 0, (byte) 255, 0, 0,
(byte) 255, (byte) 255, (byte) 255, 0, 0, (byte) 255, 0,
(byte) 255, (byte) 255, (byte) 255, 0, (byte) 255, (byte) 255,
(byte) 255, 0, 0, (byte) 128, 0, 0, (byte) 255, };
private static int[] TRIANGLE_INDICES = { 0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2,
4, 0, 1 };
private Graphics3D g3d;
private VertexArray va_vertex;
private VertexBuffer vb;
private VertexArray va_color;
private Transform tf;
private Camera camera;
private TriangleStripArray tsa;
public My3DWorld(boolean suppressKeyEvents) {
super(suppressKeyEvents);
th = new Thread(this);
g3d = Graphics3D.getInstance(); // 得到一个g3d实例
vb = new VertexBuffer();
camera = new Camera();
tf = new Transform();
tsa = new TriangleStripArray(TRIANGLE_INDICES,
new int[] { TRIANGLE_INDICES.length });
// 参数1 传入一个三角形形式的面数组,第二参数代表将参数一的数组复制到新的数组里
// 把三角带处理成正常的三点一面的形式
va_vertex = new VertexArray(VERTEX_POSITIONS.length / 3, 3, 1);
// 这里是定义空间顶点数组,第一个参数代表顶点的个数
// 第二个参数表示几个点成一个空间点;第三个参数表示每个顶点占得字节数
va_vertex.set(0, VERTEX_POSITIONS.length / 3, VERTEX_POSITIONS);
// 此方法是将一开始定义的顶点数组VERTEX_POSITIONS 设置成空间顶点(与顶点数组一一对应)
// 第一参数可以理解成从第一个顶点数组下标为0开始,
//第二参数封装的空间顶点数个数有POINTS.length/3个,
// 第三 参数传入需要转换成空间顶点的数组
va_color = new VertexArray(VERTEX_COLORS.length / 3, 3, 1);
// 这里是定义空间颜色顶点数组,第一个参数代表颜色顶点的个数(与顶点数组一一对应)
// 第二个参数表示几个点成一个空间点;第三个参数表示每个顶点占得字节数
va_color.set(0, VERTEX_COLORS.length / 3, VERTEX_COLORS);
// 此方法是将一开始定义的顶点数组VERTEX_COLORS 设置成空间顶点颜色数组
// 第一参数可以理解成从第一个顶点数组下标为0开始,
//第二参数封装的空间顶点颜色数个数有POINTS.length/3个,
// 第三 参数传入需要转换成空间顶点颜色的数组
float pc[] = { 0, 0, 1 };
vb.setPositions(va_vertex, 1.0f, pc);// @备注2
// 设定顶点位置 第一个参数 传入顶点空间数组
// 第二个参数标识对缩放大小1.0不缩放
// 第三个参数标识偏差 ,详细看下文解释的@备注2
vb.setColors(va_color);
// 设定空间颜色数组
camera.setPerspective(30, (float) this.getWidth()
/ (float) this.getHeight(), 1, 1000); // @备注3
// 设定透视投影
// 详细解释看@备注3
Transform transform = new Transform(); // @备注4
// 详细解释看@备注4
transform.postTranslate(0, 0, 10);
// 这里是设置摄像机投影位置
g3d.setCamera(camera, transform);
// 用3d画笔设定3d空间摄像机
th.start();// 启动线程
}
public void draw(Graphics g) {
try {
g3d.bindTarget(g);// @备注5
// 将画笔绑定在3d空间画笔
g3d.clear(null);
// 清屏 参数null 标识默认刷屏方式
g3d.render(vb, tsa, new Appearance(), tf);// @备注6
// 渲染 第一个参数传入一个建立图形所需要的信息,包括法线、顶点信息,颜色等
// 第二个参数标识 立体图形所需的三角形带面信息
// 第三个信息标识外观的设定这里默认,后续文章会有学习
} catch (Exception e) {
System.out.println("draw -> Error!! ");
} finally {
g3d.releaseTarget();// @备注7
}
}
public void keyPressed(int key) {
if (key == AbsCanvas.up || key == AbsCanvas.down)
tf.postRotate(10, 1, 0, 0);// @备注8
else if (key == AbsCanvas.left || key == AbsCanvas.right)
tf.postRotate(10, 0, 1, 0);// @备注8
}
protected void keyRepeated(int key) {
keyPressed(key);
}
public void run() {
while (true) {
try {
draw(this.getGraphics());
flushGraphics();// midp2.0 刷新画笔
Thread.sleep(100); // 休眠线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
模拟器截图:
备注1 : 这里要详细讲解下三角形带,下面引用一张图a,大家根据图示来看这个顶点数组就应该明白了!
大家看我们一开始定义的以三角带形式的顶点数组
VERTEX_POSITIONS = { -1, -1, 1, 1, -1, 1, -1,1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1 };
我们以立方体的中心为{0, 0,0},那么如果顶点 0坐标就是(-1, -1, 1) 那么顶点 2 是不是 {-1,1,1}了,肯定是!
这里坐标的三个点其实就是代表就是X轴 Y轴 Z轴
也就是说两个顶点0和顶点2这两个顶点都有共同的 -1, 1 ,而三角形带形式就是这种重复利用重复点的形式来标识了所有的立方体的顶点!
备注2:这里咱们定义了一个偏差数组 float pc[] = { 0, 0, 1 }; 为什么要以数组形式呢?其实你换种形式看看,其实是一个坐标点,
毕竟这是3D世界了 娃哈哈,其实意思就是 X轴+=0,Y轴+=0,Z轴+=1,当我们把这个偏差点传入setPositions()这个方法里以后,
也就是代表将这个立方体中心点从{0,0,0}变成了{0,0,1}这一点,如果你运行此项目当按下左右按键对其立方体进行旋转的时候,
发现立方体旋转不是围绕中心点进行的旋转了,而是以{0,0,1}这一点做的旋转;所以setPositions()其实也是对中心点的一个偏差处理。
有些同学该说为什么中心点就是{0,0,0}这一点呢,其实没人规定而是咱们一开始定义立方体数组顶点的时候就自己在心里定下了一个规定,
以{0,0,0}为中心点了。如果你一开始定义VERTEX_POSITIONS 的时候不以{0,0,0}为中心点,而是以顶点0 坐标为中心点的话,
那么顶点2这时候的顶点坐标就成了{0,2,0} ,顶点3就成了{0,2,2}那么也能写成一个三角形带形式,但是要注意你后面的颜色数组和
定义三角形带数组的时候也要以为顶点0为中心点来写噢,这点别忘了,要一一对应!
备注3:camera.setPerspective(30, (float) this.getWidth()/ (float) this.getHeight(), 1, 1000);
第一个参数指的是透视的角度!不是高度!第二个指的是屏幕宽高比例,第三个是可视范围min和max
其实这里常用还有一个方法是:camera.setParallel() 这两个方法以及备注5在后续文章
《深度缓冲与投影》的时候再向大家讲解。
备注4:Transform transform = new Transform(); 这里咱们定义了一个变换对象,其实咱们一开始定义的成员变量里也有一个
private Transform tf;但是这里要注意,transform 是为了设置摄像机的时候同时设定了相机的位置而定义的,而tf则是对渲染立方体的
候做反转、缩放、平移等操作定义的一个变化对象,等后续文章会对渲染时这个变化对象加以说明。一定要注意这两个Transform 区别!
备注5:备注3已经说明了 ,等后续文章学习《深度缓冲与投影》的时候再向大家讲解。
备注6:这里就是为了强调与备注4的Transform两个对象的区别!
备注7:这里调用 releaseTarget() 意思是终止渲染,大家会发现g3d.releaseTarget();这一句被写在了try catch块里,其实原因是因为
许多 Graphics3D 的方法都会抛出不可控异常,但绝大多数错误都是不可恢复的, 所以不管是否出现异常都要保证能终止渲染!
备注8:这里是对按键的操作,按键处理和对立方体操作(缩放、平移、旋转)会在后续学习文章中详细解释的。
最后给大家放出源码,希望大家一起相互交流。谢谢!
源码下载地址:http://download.csdn.net/source/2887681
分享到:
相关推荐
【标题】"j2me3D 立方体"是一个关于使用Java 2 Micro Edition (J2ME)平台开发3D图形的实践项目。在移动设备上实现3D图形是一项挑战,因为资源有限,而这个项目展示了如何在这样的环境下创建一个简单的3D立方体模型。...
原文学习地址:【J2me3D系列学习文章之一】构造我们3D世界中的第一个立方体! http://blog.csdn.net/xiaominghimi/archive/2010/12/07/6059650.aspx
### J2ME的3D开发教程:探索移动设备上的三维世界 #### 引言:步入移动3D开发的殿堂 随着科技的飞跃发展,移动设备的功能早已超越了基本的通讯需求,它们成为了集娱乐、多媒体体验及游戏于一体的综合性平台。其中...
在描述中提到的 "j2me 3D CS demo" 很可能是展示 J2ME 能力的一个客户端-服务器(Client-Server)应用程序演示,可能是一个基于 3D 的游戏或者交互式应用。 在 J2ME 中实现 3D 图形通常涉及到以下几个关键知识点: ...
开发者需要创建一个表示魔方每个面的二维图像,并将它们合理地组合在一起,形成一个可旋转的3D立方体。这通常涉及到坐标系统转换和矩阵运算,以确保各个面在旋转时能正确显示。此外,为了实现魔方的转动,可能采用了...
“Sonyericsson Mobile Java 3D V1.1.pdf”教程中,可能会包含详细的代码示例,演示如何使用JSR 184 API创建一个简单的3D旋转立方体。这个示例涵盖了模型加载、纹理应用、摄像机设置等基本步骤,对于初学者来说非常...
《J2ME3D手机游戏开发详解》是针对移动设备上的3D游戏开发的一本专业书籍,其随书源码提供了丰富的实践示例,帮助读者深入理解J2ME平台上的3D游戏编程技术。J2ME,全称为Java Micro Edition,是Java平台的一个子集,...
总的来说,J2ME 3D手机游戏开发是一个涵盖了多方面技术的领域,包括3D图形编程、物理模拟、音频处理以及性能优化等。初学者通过学习提供的代码和书籍,可以逐步掌握这个领域的核心知识,并有能力开发出自己的3D手机...
标题中的“一个J2ME的3D菜单”指的是在Java 2 Micro Edition(J2ME)平台上实现的一种具有三维效果的菜单系统。J2ME是Java的一个子集,主要用于开发移动设备、嵌入式系统等有限计算资源的平台,如早期的手机游戏和...
J2ME 3D手机游戏开发详解 完整版 分为3部分
在这个压缩包中的"Chapter9"可能是指一个教程或指南的第九章,通常教程会按章节逐步讲解,从基础到进阶,因此“Chapter9”可能包含了更复杂或高级的3D游戏开发技术,例如光照、纹理映射、模型加载、动画处理、碰撞...
《J2ME 3D手机游戏开发详解》一书涵盖了从基础到实战的J2ME 3D游戏开发全过程。J2ME,全称为Java 2 Micro Edition,是Java平台的一个子集,专为资源有限的移动设备如手机设计。在J2ME中开发3D游戏,需要理解其核心...
Java Micro Edition(J2ME)是Java平台的一个子集,专为资源有限的设备如移动电话和嵌入式系统设计。在游戏开发领域,尽管现代手机和游戏设备倾向于使用更强大的平台,如Android和iOS,但在早期,J2ME因其跨平台性和...
在本文中,我们将深入探讨如何使用Java 2 Micro Edition(J2ME)平台进行3D场景设计,特别是创建和操作3D五角星。J2ME是Java的一个轻量级版本,主要用于移动设备和嵌入式系统,它提供了一种在这些受限环境中实现3D...
《J2ME中3D实例讲义》是一份详尽的教程资料,旨在帮助开发者深入理解和实践在Java 2 Micro Edition (J2ME)平台上构建3D图形应用。J2ME是Java为移动设备和嵌入式设备设计的一个轻量级开发平台,尽管资源有限,但通过...
MascotCapsule是Sun公司提供的一个用于J2ME的3D图形库,主要特点包括: - **创建和绘制3D模型**:提供了丰富的API来创建和渲染3D模型。 - **3D变换和运算函数**:支持各种3D变换操作。 - **透明纹理精灵实现的烟雾...
在Java ME(J2ME)平台上,开发3D应用程序是一个挑战,因为它的资源有限,但通过JSR 184(Mobile 3D Graphics API)的引入,开发者得以实现3D图形的绘制和交互。本项目名为“j2me 3D 旋转的头”,显然是一个基于JSR ...
我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我的第一个j2me游戏代码我...