在Java移动3D中用到的纹理图像的大小必须是2的非负指数幂,如(2,4,8,16,32,64,128,256)。
我们首先建立棱锥,并设置将要使用的纹理坐标。尽管棱锥只有五个点组成,但是为了能够使纹理坐标与棱锥顶点正确匹配,我们还是要为棱锥的每一个侧面都指定所需要的三个顶点。
纹理坐标的值必须在从0到1的范围内,但是在程序中我们使用0到255范围内的整数值指定了纹理的坐标,所以我们使用<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on"><span lang="EN-US">1.0f</span></chmetcnv>/<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="255" unitname="F" w:st="on">255.0f</chmetcnv>这个因数将这些坐标值等比例缩小。
纹理对象的左上角对应的纹理坐标是(0,0),右下角是(1, 1)。
我们在为棱锥指定纹理坐标时,一定要清楚纹理图像一直是一个正方形,所以正上方中间的纹理坐标应该为0.5,因此我们输入127,127*(1/255) ≈ 0.5。
一定要确保TEXTURES数组和POINTS数组相匹配。点(-1, -1, 1)是棱锥前侧面的左下角,而纹理坐标的左下角是(0,1)。请注意,棱锥的底面是由两个三角形组成。
short []POINTS = new short[] {
-1,-1, 1, 1,-1, 1, 0, 1, 0, //前侧面
1,-1,1, 1,-1,-1, 0, 1, 0, //有侧面
1,-1,-1, -1,-1,-1, 0, 1, 0, //后侧面
-1,-1,-1, -1,-1, 1, 0, 1, 0, //左侧面
-1,-1, 1, 1,-1, 1, 1,-1,-1, //右底面
-1,-1, 1, 1,-1,-1, -1,-1,-1}; //左底面
// 纹理坐标在setTexCoords
short []TEXTURES = new short[] {0,255, 255,255, 127,0,
0,255, 255,255, 127,0,
0,255, 255,255, 127,0,
0,255, 255,255, 127,0,
0,0, 255,0, 255,255,
0,0, 255,255, 0,255};
VertexArray TEXTURE_ARRAY;
TEXTURE_ARRAY = new VertexArray (TEXTURES. length / 2, 2, 2);
TEXTURE_ARRAY.set (0, TEXTURES. length / 2, TEXTURES);
// VertexBuffer保存了对VertexArray对象的引用,而这些VertexArray对象可能包// 含了一系列顶点的位置、法线、颜色和纹理信息。
VertexBuffer vertexBuffer = new VertexBuffer ();
为了使用多重纹理,在具有两个纹理图像的情况下,我们需要为每一个可用的纹理对象指定坐标。setTexCoords方法实现了纹理坐标的等比例缩小。
vertexBuffer.setTexCoords (0, TEXTURE_ARRAY, (<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>/<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="255" unitname="F" w:st="on">255.0f</chmetcnv>), null);
vertexBuffer.setTexCoords (1, TEXTURE_ARRAY, (<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>/<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="255" unitname="F" w:st="on">255.0f</chmetcnv>), null);
在创建mesh后,我们创建将要使用的纹理对象。
// 装载图片
Image texImg = Image.createImage (path);
// 利用上面的图片创建纹理对象
Texture2D texture = new Texture2D (new Image2D (Image2D.RGB, texImg)); // 在表面重复纹理
texture.setWrapping (Texture2D.WRAP_REPEAT, Texture2D.WRAP_REPEAT);
// 设置混合模式.
texture.setBlending (Texture2D.FUNC_DECAL);
//设置过滤模式
texture.setFiltering(Texture2D.FILTER_NEAREST, Texture2D.FILTER_NEAREST);
纹理对象创建后,我们就要把它们添加到mesh的外观对象中。如果要移除某个纹理对象,只需要设置相应索引上的对象为null。
// 添加第一个纹理对象
meshAppearance.setTexture(0, brickTexture);
// 添加第二个纹理对象
meshAppearance.setTexture(1, multiTexture);
//移除时
meshAppearance.setTexture(0, null);
meshAppearance.setTexture(1, null);
因为Texture2D继承自Transformable类,所以它可以轻而易举利用转换得到不同的效果。利用下面的方法,我们就可以实现旋转、移动和等比例变换:
postRotate (float x, float y, float z)
translate (float x, float y, float z)
scale (float x, float y, float z)
默认情况下,一个纹理位图必须完整地填充对象的整个表面,所以如果你想使用一个宽度为256的纹理图像对一个宽度为32的表面进行贴图,那么纹理的宽度就会收缩(译者注:也就是说会将整个图片的宽度缩为32,然后贴在本填充的对象表面上)。为了避免这种情况,你可以将纹理的宽度等比例缩小8倍(32 * 8 = 256),scale(<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue=".125" unitname="F" w:st="on">0.125f</chmetcnv>, <chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>, <chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>);现在,如果你希望显示同一个纹理的其他部分,就应该使用translate方法,translate(<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue=".5" unitname="F" w:st="on"><span lang="EN-US" style="COLOR: black; LINE-HEIGHT: 150%; mso-bidi-font-size: 10.5pt"><font face="Times New Roman">0.5f</font></span></chmetcnv>,<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on"><span lang="EN-US" style="COLOR: black; LINE-HEIGHT: 150%; mso-bidi-font-size: 10.5pt"><font face="Times New Roman">1.0f</font></span></chmetcnv>,<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on"><span lang="EN-US" style="COLOR: black; LINE-HEIGHT: 150%; mso-bidi-font-size: 10.5pt"><font face="Times New Roman">1.0f</font></span></chmetcnv>)。
通过这篇文章,相信大家都已经对m3g中的纹理贴图有了一个大致的了解,下面我们再来回顾一下文中的重要内容。
纹理对象Texture2D,它是一个外观(Appearance)对象的一部分,包含了一个纹理图像和一系列的定义如何将纹理图像应用到子网眼对象表面上的属性,这些属性包括纹理图像的填充方式,过滤、混合和纹理的坐标转换。文中创建一个完整的纹理对象步骤为:
1、 创建一个图片对象,利用这个图片对象创建纹理对象。纹理图像是以Image2D对象的引用存储的。这个图像可以是Image2D中所规定的任何格式,需要注意的是,图像的宽度和高度都要为2的非负指数幂,但是二者并不一定相等。如果在程序运行中我们对Image2D对象进行了修改,那么立刻就会反映到纹理对象中,但是这个过程会产生很大的开支,例如重新生成纹理和重新分配内存等,因此在建立纹理对象以后最好不要修改Image2D对象。
2、 使用setWrapping方法设置纹理图像的重复模式。Texture2D中定义了两种纹理图片的重复模式:WRAP_CLAMP和WRAP_REPEAT,前者是指只重复一次,其实也就是没有重复,程序中画的纹理就是这种方式;后者是指无限重复,直到填充这个画面,程序中砖块的纹理就是这种方式。
3、 使用setBlending方法设置混合方式,混合是指过滤后的纹理颜色和引入的片段颜色的结合。Texture2D定义了五种混合方式:FUNC_ADD、FUNC_BLEND、FUNC_DECAL、FUNC_MODULATE和FUNC_REPLACE。程序中分别用到了FUNC_DECAL和FUNC_MODULATE。
4、 使用setFiltering方法设置过滤方式。Texture2D定义三种过滤方式:FILTER_BASE_LEVEL 、FILTER_LINEAR 和FILTER_NEAREST。请注意,这个设置仅仅是一个提示,应用程序在实现时可能忽略这个设置,根据自己的判断选择一种合适的方式。
文章的最后提到了纹理的变换,在例程中通过创建一个平面的对象并进行纹理贴图,在程序运行过程中使用了translate方法进行纹理图像的移动,从而产生了走马灯式的动态效果。下面我们看一下scale方法的使用。程序中的info.png纹理的宽高比为8/1,而创建的平面对象的宽高比也为8/1。下面我们更改组成平面对象的顶点数组为:
short[] POINTS = new short[] { -1, 0, 0, // bottom left point
1, 0, 0, // bottom right
1, 1, 0, // up right
-1, 1, 0 }; // up left
这时宽高比变为2:1,运行程序,就会得到如左下的效果,可以看到纹理图片被压缩了。接着我们使用scale设定缩放比例,在createPlane方法创建纹理的代码中添加scale(<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue=".25" unitname="F" w:st="on">0.25f</chmetcnv>, <chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>, <chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="F" w:st="on">1.0f</chmetcnv>),再次运行就可以得到右下图所示的效果。
下载源码JSR184Texture
相关推荐
通过学习这篇博客和研究提供的代码示例,开发者能够掌握JSR-184中的关键概念,从而在自己的项目中实现生动且互动的3D图形。无论是游戏开发、虚拟现实应用,还是科学可视化,理解光照和物体定向都是3D编程的基础,...
【JSR-184】是Java Micro Edition (Java ME) 中的一项标准,全称为“Mobile 3D Graphics API”,它定义了一套用于在移动设备上进行3D图形编程的接口。JSR-184的目标是让开发者能够在资源有限的移动设备上创建高质量...
在提供的`src`和`res`文件中,`src`可能包含示例代码,用于演示如何使用JSR-184 API创建3D对象和交互。`res`文件夹可能包含纹理图像、3D模型文件以及其他资源,这些资源可以与代码配合使用,以展示一个完整的3D应用...
《3-D Game Development on JSR-184 v1_0_3》是关于使用Java 3D技术在J2ME平台上开发3D游戏的一份重要资料,它为初学者提供了一个宝贵的入门教程。JSR-184,全称为Java ME 3D API,是Java Micro Edition(J2ME)平台...
【JSR-184】是Java Micro Edition (Java ME) 中的一项标准,它定义了Mobile 3D Graphics API,也称为M3G。M3G是为了在移动设备上实现高性能的3D图形渲染而设计的,使得开发者可以创建丰富的3D游戏和应用。这篇【3D...
JSR-000231(Java Specification Request 231)是这个项目的官方编号,标志着它在Java Community Process中的地位,确保了其与Java平台的兼容性和标准化。 jogl 1.1.0包含了多个核心组件,如`jogl.jar`和`gluegen....
JSR-184为开发者提供了一套接口和类,用于在J2ME环境中创建3D图形。通过这个API,开发者可以构建复杂的3D模型、动画和交互式场景,而无需依赖于特定硬件的图形加速器。JSR-184的目标是简化移动设备上的3D编程,使得...
通过这些库文件,开发者可以学习到如何在Java中设置OpenGL上下文、绘制3D图形、处理输入事件、管理纹理和顶点缓冲等。同时,`jogl-demos`还提供了对现代OpenGL特性,如着色器、顶点数组对象和帧缓冲对象的支持,帮助...
**JSR 184 API** 是Java ME(J2ME)平台中的一项规范,全称为"Mobile 3D Graphics API",它为移动设备提供了3D图形编程接口,使得开发者能够在小型设备上创建和展示复杂的三维图形。这项技术极大地扩展了J2ME应用...
在JSR 184中,它通过提供一系列的类和方法来实现这一目标。这些类包括但不限于几何对象(如立方体、球体等)、纹理、光照、相机视角控制等关键元素,它们共同构成了3D场景的基础。 **M3G API** M3G,即Mobile 3D ...
JSR(Java Specification Requests)是Java社区进程中的一个关键部分,用于提出和定义新的Java技术标准。JSR 184,全称为“Mobile 3D Graphics API”,是一项针对J2ME平台的规范,旨在提供在移动设备上进行3D图形...
【标题】"Himi"所涉及的是一种基于J2ME平台的3D游戏开发API,主要利用了JSR184规范。这个标题暗示我们将会探讨如何使用Java技术在移动设备上创建三维游戏。 【描述】"j2me3D游戏开发api ,jsr184"表明该资源是关于...
教程内容源自Sony Ericsson Mobile Communications AB,涵盖了JSR-184和Mascot Capsule v3两个关键标准,它们都是为了在J2ME平台上实现3D图形支持而制定的。 **JSR-184(Mobile 3D Graphics API)** 是Java ...
JSR-184是Java Community Process的一项提案,定义了一组标准API,用于在J2ME平台上创建3D图形内容。通过这些API,开发者可以轻松地在手机上创建3D场景、纹理映射等效果,大大提高了手机游戏的表现力。 #### 七、...
Java ME(Mobile Edition)提供了许多游戏开发的API,如JSR-184(M3G)和JSR-234(Accelerometer API)。在移植到Android时,需要找到对应的替代方案: 1. **输入系统**:Java ME的KeyListener和PointerListener在...
通过本资料集中的"dg_java_3d_cn_r33a.pdf",读者可以深入了解JSR184和Micro3D的基础知识,包括如何初始化3D环境、创建3D对象、设置光照和纹理、实现3D动画等。文档详细阐述了3D图形的基本原理,如坐标系统、投影和...
M3G是JSR-184的一部分,提供了一套3D图形接口,可以创建复杂的3D场景和对象。 2. **物体建模**:在3D菜单中,每个菜单项可能被表示为3D物体,如立方体、球体或更复杂的形状。这些物体需要通过顶点坐标、纹理坐标和...