如何在JMonkey Engine库中绘制直线

3
我正在尝试使用JMonkey引擎3D图形库在我指定的3D顶点之间绘制直线。当然,JMonkey优化用于导入模型,但我了解它也可以用于“内部”创建自定义形状。
例如,如果我要在以下点之间绘制:
(2,0,0)
(-1,0,1)
(0,1,1)
(1,1,1)
(1,4,0)
那么我会得到如下结果:
JMonkey straight lines
1个回答

6

更新

Jmonkey的最新版本中有一个Line类,使这个过程变得更加简单。详情请点击此处

原回答

JMonkey中的线条是由自定义网格创建的,您需要将顶点作为浮点位置缓冲区和指数(连接哪些顶点)作为短整型缓冲区提供。本回答基于一个关于网格缓冲区的论坛帖子JMonkey高级图形维基页面的松散结构。

以下是一个示例程序:

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.shape.Box;
import com.jme3.util.BufferUtils;

public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        
        Vector3f[] lineVerticies=new Vector3f[5];
        
        lineVerticies[0]=new Vector3f(2,0,0);
        lineVerticies[1]=new Vector3f(-1,0,1);
        lineVerticies[2]=new Vector3f(0,1,1);
        lineVerticies[3]=new Vector3f(1,1,1);
        lineVerticies[4]=new Vector3f(1,4,0);
        
        plotLine(lineVerticies,ColorRGBA.Blue);
    }

    public void plotLine(Vector3f[] lineVerticies, ColorRGBA lineColor){
        Mesh m = new Mesh();
        m.setMode(Mesh.Mode.Lines);
      

        m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(lineVerticies));
        
        short[] indexes=new short[2*lineVerticies.length]; //Indexes are in pairs, from a vertex and to a vertex
        
        for(short i=0;i<lineVerticies.length-1;i++){
            indexes[2*i]=i;
            indexes[2*i+1]=(short)(i+1);
        }
        
        m.setBuffer(VertexBuffer.Type.Index, 2, indexes);
        
        m.updateBound();
        m.updateCounts();

        Geometry geo=new Geometry("line",m);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", lineColor);
        geo.setMaterial(mat);
        
        rootNode.attachChild(geo);
    }
    
    
    @Override
    public void simpleUpdate(float tpf) {
        //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}

在这个程序中,网格类型被设置为

m.setMode(Mesh.Mode.Lines);

这表示网格会期望一些索引对,这些索引指示哪些顶点连接到哪些顶点(常用的其他选项包括m.setMode(Mesh.Mode.Triangles);,此时它将期望一组三个索引,指示由哪些顶点组成了三角形)。
在其最基本的状态下,顶点缓冲区期望 x1, y1, z1, x2, y2, z2, x3, ... 的输入,其中没有标记指示一个顶点的结束和另一个顶点的开始。因此,以下内容将输入3个顶点到缓冲区中:(1.1、1.2、1.3)、(2.1、2.2、2.3)和(3.1、3.2、3.3)。
m.setBuffer(VertexBuffer.Type.Position, 3, new float[]{1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 3.1, 3.2, 3.3});

索引缓冲区将连接0->1, 1->2。

 m.setBuffer(VertexBuffer.Type.Index, 2, new short[]{0, 1, 1, 2});

请注意,每个缓冲区的第二个参数表示有多少个条目对应于一个“操作”,例如顶点是3D的,因此参数为3,而索引是从->到成对出现的,因此参数为2。
但是,有一些实用方法可以使其更易于使用,而不是输入x1、y1、z1、x2、y2、z2、x3等,BufferUtils.createFloatBuffer() 方法允许您使用 Vector3f 数组,例如:
m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(lineVerticies));

其中lineVerticies的类型为Vector3f[]。但值得注意的是,这样做会带来性能损失,如果您可以直接创建float[],将避免不必要的转换(特别是对于大型网格非常重要)。

m.updateBound();m.updateCounts();可能看起来并不是确保线条绘制的必要条件;然而,没有它们,线条可能会被错误地裁剪(当它仍在屏幕上时,显卡可能认为它不在屏幕内,并“不费力地”渲染它)。


@Aquarius。我相信这可能是一个更简单的解决方案。 - Richard Tingle
尽管我认为你的代码可以实现多行,而这是单行的;你的代码也可以成为贡献 :) - Aquarius Power

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接