`
hjk685
  • 浏览: 102433 次
  • 来自: ...
社区版块
存档分类
最新评论

JME3 官方教程翻译 - 自定义网格形状

阅读更多

 

Custom Mesh Shapes

自定义网格形状

Use the Mesh class to create custom shapes that go beyond Quad, Box, Cylinder, and Sphere, even procedural shapes are possible. Thank you to KayTrance for providing the sample code!

In this tutorial, we (re)create a very simple rectangular mesh, and we have a look at different ways of coloring it. A flat rectangle may not look useful because it's exactly the same as a com.jme3.scene.shape.Quad. We choose this simple example in order to show you how to build any shape out of triangles – without the distractions of more complex shapes.

 

使用 Mesh 类来创建自定义形状,他超出了方形 、盒子、圆筒和球体等形状的,甚至来制作程序的形状也是可能的。在这里谢谢提供样品密码的 KayTrance, 谢谢你!

在这个指导中,我们 (关于)创建非常简单的矩形网格,而且我们用不同方法给它涂颜色。因为它完全和 same as a com.jme3.scene.shape.Quad 相同,所以一个平坦的长方形可能没有什么用。我们选择这个简单的例子主要为了要教你该如何从三角形建立任何想要的形状-没有比较复杂形状更有用处。

Polygon Meshes 多边形网格

Polygon meshes are made up of triangles. The corners of the triangles are vertices. So, when ever you create a new shape, you break it down into triangles.

 

多边形网格是由三角形组成的。三角形的角是顶点所以无论何时只要你创建新的形状,你都必须把它们拆散为三角形。

 

Let's look at a cube. A cube is made up of 6 rectangles. Each rectangle can be broken down into two triangles. This means you need 12 triangles to create a cube mesh. You also need to know the 8 corner coordinates (vertices). The trick is that you have to specify the vertices in a certain order: Each triangle separately, counter-clockwise.

 

我们先来分析一下立方体,一个立方体由 6 矩形构成,每一个矩形都可以分解为两个三角形。这一就是说你需要 12 个三角形来组成一个立方体网格。这时你就需要 8 个角的坐标(顶点)。所以你不得不按照一定顺序指定顶点。

Sounds worse than it is – here is an example:

实际比这还要糟糕(复杂)请看线面这个例子:

 

Creating a Quad Mesh 创建一个四边形网格

 

Okay, we want to create a Quad. A quad has four vertices, and is made up of two triangles.

 

好下面我们创建一个四边形。一个四边形包含四个顶点,由两个三角组成。

The base class for creating meshes is com.jme3.scene.Mesh.

基础的创建四边形的类是 com.jme3.scene.Mesh 。使用方法如下:

 

 

Mesh m = new Mesh();

 

 

Vertices 顶点

 

To define your own shape, determine its vertex positions in space. Store them in an array using com.jme3.math.Vector3f. For a Quad, we need four vertices: Bottom left, bottom right, top left, top right. We name the array vertices[].

 

确定你自己的形状,确定它所有的顶点在空间中的位置,用 com.jme3.math.Vector3f 这个类型的数组来储存它们。我们需要四个顶点,左下、右下、左上、右上,(这个顺序很重要)我们以 vertices[] 来命名这个数组。

 

 

Vector3f [] vertices = new Vector3f[4];

vertices[0] = new Vector3f(0,0,0);

vertices[1] = new Vector3f(3,0,0);

vertices[2] = new Vector3f(0,3,0);

vertices[3] = new Vector3f(3,3,0);

 

 

Texture Coordinates 纹理坐标

 

Next, define the Quad's 2D texture coordinates for each vertex, in the same order: Bottom left, bottom right, top left, top right. We name this array texCoord[]

 

下面,定义四边形每个顶点的 2D 纹理坐标,用和上面类似的方法:左下、右下、左上、右上。给这个数组起名字叫: texCoord[]

 

 

Vector2f[] texCoord = new Vector2f[4];

texCoord[0] = new Vector2f(0,0);

texCoord[1] = new Vector2f(1,0);

texCoord[2] = new Vector2f(0,1);

texCoord[3] = new Vector2f(1,1);

 

 

Connecting the Dots 链接这些点

 

Next we turn the unrelated coordinates into triangles – We define the order in which the mesh is constructed. Think of these indexes as coming in groups of three. Each group of indexes describes one triangle. Note that the vertices are giving counter-clockwise!

 

下面我们转换这些无关的坐标为一个三角形,我们定义创建哪些三角形的命令。想想这些索引会有三组, 每一个索引组描述一个三角。注意顶点是逆时针旋转的。

 

 

int [] indexes = { 2,0,1, 1,3,2 };

 

  • The 2,0,1 triangle starts at top left, continues bottom left, and ends at bottom right.
  • The 1,3,2 triangle start at bottom right, continues top right, and ends at top left.
  • 索引顺序 2,0,1 起始于左上角,经过左下角,最后在右下角结束。
  • 索引顺序 2,0,1 起始于右下角,经过右上角,在左上角结束。

 

 

2\ 2-3

|   \    |         Counter-clockwise 逆时针旋转。

|     \   |        

0–1\1

 

Setting the Mesh Buffer 设置网格缓冲器

 

The Mesh data is stored in a buffer. 网格数据被存储在一个缓冲器中。

  1. Using com.jme3.util.BufferUtils, we create three buffers for the three types of information we have:

使用 com.jme3.util.BufferUtils ,我们创建三个缓冲器对应我们三种不同类型的信息:

  1.  
    • vertex positions,
    • texture coordinates,
    • indices.
    • 顶点坐标
    • 纹理坐标
    • 索引顺序

 

  1. We assign the data to the appropriate type of buffer inside the mesh object. The three buffer types are taken from an enum in com.jme3.scene.VertexBuffer.Type.

在网格对象中我们分配这些数据到合适类型的缓冲器。这三个缓冲器类型来自于枚举类型类 com.jme3.scene.VertexBuffer.Type

  1. The third parameter describes the number of components of the values. Vertex postions are 3 float values, texture coordinates are 2 float values, and the indices are single ints.

这三个参数描述组成不同部分的值。顶点坐标是 3 float 值,纹理坐标是 2 float 值,索引是 int 类型。

 

 

m.setBuffer(Type.Position , 3, BufferUtils.createFloatBuffer(vertices));

m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

m.setBuffer(Type.Index,    1, BufferUtils.createIntBuffer(indexes));

 

 

Our Mesh is ready! Now we want to see it. 这时网格已经做好了,我们来看看它。

 

Using the Mesh in a Scene 在场景里使用网格

 

We create a com.jme3.scene.Geometry, apply a simple color material to it, and attach it to the rootNode to make it appear in the scene.

我们创建一个 com.jme3.scene.Geometry 对象,给它使用一个简单的材质,在把它绑定到 rootNode 节点上让它出现在场景中。

 

Geometry geom = new Geometry("OurMesh", m);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

mat.setColor("m_Color", ColorRGBA.Blue);

geom.setMaterial(mat);

rootNode.attachChild(geom);

 

Ta-daa!

 

Optional: Vertex Colors 可选的:顶点颜色

 

Vertex coloring is a simple way of coloring meshes. Instead of just assigning one solid color, each vertex (corner) has a color assigned. The faces between the vertices are then colored with a gradient.

 

顶点颜色是一个给网格着色简单的方法。代替刚刚的单一颜色,每个顶点都给分配一种不同的颜色。这个面上的颜色就会有从一个顶点到另一个顶点颜色的过渡。

 

We will use the same mesh m as defined above, but with a special VertexColor material.

 

我们将使用相同的网格对象 m 但是使用特殊的顶点着色材质。

 

 

Geometry coloredMesh = new Geometry ("ColoredMesh", m);

Material matVC = new Material(assetManager, "Common/MatDefs/Misc/VertexColor.j3md");

 

 

We create a float array color buffer.

我们创建一个浮点型数组颜色缓冲器。

  • We assign 4 color values, RGBA, to each vertex.
    • To loop over the 4 color values, we use a color index
  • 我们先指定四个颜色值, RGBA, 给每一个顶点。
    • 在四个颜色值构成一个循环,我们使用颜色索引。

 

int colorIndex = 0;

 

  • The color buffer contains four color values for each vertex.
    • The Quad in this example has 4 vertices.
  • 颜色索引包含四个颜色值对应每个顶点
    • 四边形有四个顶点。

float[] colorArray = new float[4*4];

  •  
    • Tip: If your mesh has a different number of vertices, you would write:
    • 提示:如果你的网格有不同的顶点数,你应该写成:

float[] colorArray = new float[yourVertexCount * 4]

We loop over the colorArray buffer to quickly set some RGBA value for each vertex. As usual, RGBA color values range from 0.0f to 1.0f. The values we use here are quite arbitrary, we are just trying to give every vertex a different RGBA value (a purplish gray, purple, a greenish gray, green, in the screenshot), without writing too much code. For your own mesh, you'd choose the values the color buffer depending on which color you want the mesh to have.

 

我们循环这个颜色数组缓冲来快速设置 RGBA 的值给每一个顶点通常, RGBA 的值取于 0.0 1.0 之间,这里我们随意取几个数值,我们仅仅来给每一个顶点一个不同颜色的实验。(暗紫色、紫色、暗绿色、绿色)这些都没有太多的代码。对于我们的网格,需要选择你像个网格用的颜色值来替换掉颜色缓冲器中的颜色值。

 

for(int i = 0; i < 4; i++){

   // Red value (is increased by .2 on each next vertex here)

   colorArray[colorIndex++]= 0.1f+(.2f*i);

   // Green value (is reduced by .2 on each next vertex)

   colorArray[colorIndex++]= 0.9f-(0.2f*i);

   // Blue value (remains the same in our case)

   colorArray[colorIndex++]= 0.5f;

   // Alpha value (no transparency set here)

   colorArray[colorIndex++]= 1.0f;

}

 

Next, set the color buffer. An RGBA color value contains four float components, thus the parameter 4.

 

下面设置颜色缓冲器。一个 RGBA 颜色值包含了 4 个部分的值,所以这里参数用四。

 

 

m.setBuffer(Type.Color , 4, colorArray);

coloredMesh.setMaterial(matVC);

 

 

Now you see a gradient color extending from each vertex.

现在你可以看到渐变颜色从每一个顶点发射出来。

 

Optional: Point Mode 可选的:点模型

Alternatively, you can show the vertices as colored points instead of coloring the faces.

作为选择,你可以使用着色的点显示顶点,而不像上面一样显示面。

 

Geometry coloredMesh = new Geometry ("ColoredMesh", cMesh);

...

m.setMode(Mesh.Mode.Points);

m.setPointSize(10f);

m.updateBound();

m.setStatic();

Geometry points = new Geometry("Points", m);

points.setMaterial(mat);

rootNode.attachChild(points);

 

rootNode.attachChild(coloredMesh);

 

 

This will result in a 10 px dot being rendered for each of the four vertices. The dot has the vertex color you specified above. The Quad's faces are not rendered at all. This can be used for a special debugging or editing mode.

 

这种设置将使用十个像素点来渲染每一个顶点。这些点会精确地显示你指定的颜色。四边形的面不会被渲染,这种方式常被用在专用的测试或者编辑模型中。

 

Front and Back Faces 前后面

 

By default, jME3 optimizes a scene by culling all backfaces. It determines which side the front or backface of a mesh is by the order of the vertices. The frontface is the one where the vertices are specified counter-clockwise.

 

对于默认的情况, JME3 会使用剔除所有的背面的方式来优化场景。这就必须指出模型中哪些面是正面哪些面是反面,这个规定就是有顶点的顺序来得到的。正面是顶点链接顺序为逆时针方向的一面。

 

This means you mesh, as created above, is invisible when seen from “behind”. This may not be a problem and is often even intended. If you use the custom meshes to form a polyhedron, or flat wallpaper-like object, rendering the backfaces (the inside of the polyhedron) would indeed be a waste of resources.

 

 

这就是说刚才创建的网格从后面看是什么也看不到的。这可能不会出问题并且通常都会这么做。如果你使用自定义网格制作一个多面体,或者做一张壁纸,这时去渲染他的背面是很浪费资源的。

In case that your use case requires the backfaces to be visible, you have two options:

有时你需要同时显示正反两面时,你可以使用两种方式

  • If you have a very simple scene, you can just deactivate backface culling for this one mesh's material.
  • 如果你有一个简单的场景,你可以将该材质的剔除背面设置为无效。

 

mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off));

 

  • The recommended solution is to specify each triangle twice, the second time with the opposite order of vertices. The second, reversed triangle makes up the backface.
  • 一般的做法是在指定顶点链接索引时,每个三角面都指定两次,第二次指定时和第一次方向相反。正好就是第二次指定颠倒了第一次的顺序。
    int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 };

 

我的代码

 

/**

  *

  * @author zbp

  */

public class MeshTer extends SimpleApplication{

 

    @Override

    public void simpleInitApp() {

        Mesh m=new Mesh();

        Quad qq=new Quad(5,2);

 

        // 顶点坐标

        Vector3f[] v=new Vector3f[5];

        v[0]= new Vector3f(0,0,0);

        v[1]=new Vector3f(0,2,0);

        v[2]=new Vector3f(1,2,0);

        v[3]=new Vector3f(1,0,0);

        v[4]=new Vector3f(2,1,0);

 

        // 纹理坐标

        Vector2f[] texCoord=new Vector2f[5];

        texCoord[0] = new Vector2f(0,0);

        texCoord[1] = new Vector2f(0,1);

        texCoord[2] = new Vector2f((float) 0.5,1);

        texCoord[3] = new Vector2f((float) 0.5,0);

        texCoord[4] = new Vector2f(1,1);

 

        // 连接索引

        int index[]={4,3,2,3,0,1,3,1,2};//

        //int index[]={0,3,1,1,3,2,2,3,4};// 只按照逆时针方向的规则来连接点,面可以全部显示 , 网格显示时有的边没有闭合

        //int index[]={0,1,3,1,3,2,2,3,4};// 1 个三角面顺时针转 ,面可以全部显示 , 网格显示时有的边没有闭合

        //int index[]={0,3,1, 1,2,3, 3,4,2};// 2 个三角面顺时针转,面可以全部显示 , 网格显示时有的边没有闭合

        //int index[]={0,3,1, 1,3,2, 2,4,3};// 3 个三角面顺时针转,面可以全部显示 , 网格显示时有的边没有闭合

        //int index[]={1,3,0, 1,2,3, 2,4,3};// 所有三角面顺时针转,面可以全部显示 , 网格显示时有的边没有闭合

        //int index[]={0,3,1,2,1,3,2,3,4};// 下一个三角面起点不是上一个的重点,面可以全部显示 , 网格显示时有的边没有闭合

 

        m.setBuffer(Type.Position,3, BufferUtils.createFloatBuffer(v));

        m.setBuffer(Type.TexCoord,2, BufferUtils.createFloatBuffer(texCoord));

        m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(index));

 

        /* 以线框模式显示网格 */

        m.setMode(Mesh.Mode.LineLoop);//

        m.updateBound();

        m.setStatic();

        /* 结束 */

 

        Geometry g=new Geometry("myMesha",m);

        Material mm=new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

        mm.setColor("m_Color", ColorRGBA.Blue);

        g.setMaterial(mm);

 

        this.rootNode.attachChild(g);

 

    }

   

    public static void main(String[] args) {

        MeshTer mt=new MeshTer();

        mt.start();

    }

 

}

 

通过我的实验,这个 index 是很重要。通过 index 中指定的顺序连接各个点,但是如果用线框模式显示时,就会有不闭合的边,很难看,但是现在还不知道是否影响程序。默认情况下绘制连接线时也是用的是 index 中的这个顺序,唯一不同的是顺序中的第一个点和最后一个点要单独再连接一次。

上图这种情况 031023 这个顺序也行,可能这个说明不太合适,有高手请给予指教。

 

 

 

  • 大小: 5.8 KB
分享到:
评论
3 楼 hjk685 2011-04-08  
对不起jasoncool,这么晚回复,这个问题我也没做过,但是你说的城市场景应该分为地形和建筑两块为主要内容,不应该是整体的(我认为),再者CAD生成地形我没做过,3DMax倒是做过,你要又需要联系我。
2 楼 jasoncool 2010-12-30  
网格形状是否可以使用在省城地形上呢?
我想通过CAD图形生成地形,不知道怎么从CAD的图里读取数据啊!
楼主有研究过吗?
1 楼 hjk685 2010-11-29  
本人翻译能力有限,所以使用中英文对照方式以供参考,大家看了有什么意见给我留言。

相关推荐

    JME中文教程.pdf

    - **自定义网格**:通过编写代码自定义模型的形状,例如创建一个简单的立方体。 ### 结语 jMonkeyEngine3以其强大的功能和简洁的API设计,在3D游戏开发领域占据了一席之地。无论是初学者还是经验丰富的开发者,都...

    jme3游戏demo rise-of-mutants

    《jme3游戏开发:Rise of Mutants》 在IT行业中,游戏开发是一个充满创新和技术挑战的领域,而Java语言并非通常首选的游戏开发工具。然而,随着技术的进步,Java也逐渐进入了游戏开发的舞台,其中JMonkeyEngine...

    JME3中文教程(ZBP第一版)

    本教程是针对JME3的中文翻译版本,旨在帮助中文用户更好地理解和掌握这个强大的工具。 JME3的主要特点包括: 1. **高性能图形渲染**:JME3支持现代图形API,如OpenGL,能够高效地处理复杂的3D模型和场景,提供流畅...

    联想的JME2207P键盘驱动

    标题中的“联想的JME2207P键盘驱动”是指专门为联想品牌的一款键盘型号为JME2207P的设备设计的驱动程序。在计算机硬件系统中,驱动程序是连接操作系统与硬件设备的关键软件,它使得操作系统能够识别并控制特定硬件,...

    jme3 api(精华chm)

    com.jme3.animation com.jme3.app com.jme3.app.state com.jme3.asset com.jme3.asset.pack com.jme3.asset.plugins com.jme3.audio com.jme3.audio.joal ...jme3tools.preview

    JME3学习文档

    ### JME3游戏开发引擎中文学习指南 #### 引言 JME3,全称jMonkeyEngine3,是一款开源的3D游戏开发引擎,专为Java开发者设计,旨在简化3D游戏和应用程序的开发过程。本文档将详细介绍如何在Netbeans6.x环境下搭建...

    JME教程.rar

    3. **用户界面设计**:学习使用MIDP提供的UI组件创建交互式界面,以及如何自定义Canvas实现复杂图形绘制。 4. **数据存储**:了解如何在受限的设备上持久化数据,如使用Record Management System (RMS)。 5. **网络...

    2015jme3指南

    《2015jme3指南》是一份关于Java Media Engine 3 (JME3)的详细教程,主要面向对游戏开发感兴趣的开发者。JME3是Java平台上的一个开源3D游戏开发框架,它提供了丰富的功能,使得开发者可以快速创建高性能的3D应用和...

    JME程序设计实例教程

    **JME程序设计实例教程详解** Java Micro Edition(JME),又称为Java 2 Micro Edition,是Java平台的一个子集,主要用于开发和部署在资源有限的设备上的应用程序,如移动电话、PDA、智能家电等嵌入式系统。本教程...

    java8看不到源码-JME3-JFX:用于JME的JFXGui桥接器,具有用于常见用例的有用实用程序

    jme-3.0.10 兼容): 版本:1.+ 分支:jme_3.0 JME3-JFX 需要 java 8,但是可以使用 java 7 在纹理上绘制视频。对于 jME SDK,您应该创建一个 java 8 平台,但是 java8 支持非常糟糕(因为它基于 netbeans 7)。 ...

    JME初级教程(持续跟新)

    Java Media Engine (JME), 也称为jMonkeyEngine 3 (JME3), 是一个开源的游戏开发引擎,专为快速创建3D游戏而设计。...始终保持对JME3官方文档和社区论坛的关注,将有助于你保持最新技术和最佳实践的同步。

    jme3材质基础知识

    jME3的材质系统允许你灵活地控制这些因素,通过调整材质参数和自定义着色器,你可以创建出各种各样的视觉效果。 在提供的"jMonkeyEngine3 材质.docx"文档中,你应该能找到更深入的教程和示例代码,帮助你理解和应用...

    jme3-clj-aide:JMonkeyEngine3 + Clojure-Android + AIDE 示例项目

    同时,JME3还具有良好的社区支持,拥有丰富的教程和资源库,对于初学者和资深开发者都非常友好。 接下来是Clojure的角色。Clojure是一种运行在Java虚拟机上的编程语言,它的语法简洁,支持函数式编程,这使得代码更...

    JME3 JAVADOC

    本文档是JME 的javadoc 文档 JME是一个高性能的3D图形API,采用LWJGL作为底层支持。它的后续版本将支持JOGL。JME和Java 3D具有类似的场景结构,开发者必须以树状方式组织自己的场景。JME有一套很好的优化机制,这...

    jme8002b蓝牙键盘驱动

    jme8002b蓝牙键盘驱动

    JME的文件格式及支持的文件格式

    **JMonkeyEngine 3 (JME3) 文件格式详解** JMonkeyEngine 3(简称JME3)是一款开源的游戏开发引擎,专为构建3D游戏和应用而设计。它支持多种文件格式,使得开发者能够方便地导入和管理游戏资源。以下是对JME3支持的...

    TankBattle3D-jMEGame:塔防游戏。 SGGames。 由JME3提供支持。 libgdx-ai-jme的示例

    本项目"TankBattle3D-jMEGame"正是这样一个以Java为基础,结合了JMonkey Engine 3 (JME3) 和 Libgdx-ai 技术的3D塔防游戏。本文将深入探讨该项目中所应用的关键技术和设计思路。 首先,JMonkey Engine 3(简称JME3...

    ant-jme.jar.zip

    标题“ant-jme.jar.zip”指的是一个压缩文件,其中包含了两个关键元素:ant-jme.jar和ant.license.txt。这个文件主要与Java开发工具有关,特别是Apache Ant和Java Micro Edition (JME)。 Apache Ant是一个Java库和...

Global site tag (gtag.js) - Google Analytics