How can I draw a straight line in the JMonkey Engine library

我只是一个虾纸丫 提交于 2020-01-01 16:48:35

问题


I'm trying to draw straight lines between 3D vertices that I specify using the JMonkey Engine 3D graphics library. JMonkey is of course optimised for importing models but I understand it can be used to create custom shapes "internally" as well.

So for example if I was to try to plot between:
(2,0,0)
(-1,0,1)
(0,1,1)
(1,1,1)
(1,4,0)

Then I would get:


回答1:


Update

In the most recent version of Jmonkey a Line class exists which makes this process far simpler. This is detailed here.

Original answer

Lines in JMonkey are created with custom meshes to which you give the vertices as a position buffer of floats and the indices (which vertices connect to which) as a buffer of shorts. This answer is loosly based upon a forum thread on mesh buffers and the JMonkey advanced graphics wiki page

An example program would be as follows

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
    }
}

In this program the mesh type is set as

m.setMode(Mesh.Mode.Lines);

This indicates that the mesh will expect pairs of indexes that indicate which verticies are connected to which (other options commonly used include m.setMode(Mesh.Mode.Triangles); in which case it would expect sets of three indices indicating which vertices made up the triangles).

In its most basic state the Vertex buffer expects x1, y1, z1, x2, y2, z2, x3, ... with no demarcation between where one vertex ends and the other begins. So the following would enter 3 vertices into the buffer; (1.1, 1.2, 1.3), (2.1, 2.2, 2.3) and (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});

And the index buffer would connect then 0-->1 1-->2

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

Note that the second argument for each buffer indicates how many entries correspond to a single "operation", for example the vertices are 3D so the argument is 3 and the indices are in from-->to pairs so the argument is 2.

There are however utility methods that makes this more pleasant to use, instead of entering x1, y1, z1, x2, y2, z2, x3, ... the BufferUtils.createFloatBuffer() method allows you to use an array of Vector3f instead, so

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

where lineVerticies was of type Vector3f[]. It's worth noting however that there is a performance hit for doing so, if you can create the float[] directly it will avoid an unnecessary conversion (especially important for large meshes).

m.updateBound(); and m.updateCounts(); may appear to not be essential to ensure the line is drawn; however without them the line can be culled incorrectly (when it is still on screen the graphics card can believe it isn't and "not bother" to render it)



来源:https://stackoverflow.com/questions/17424781/how-can-i-draw-a-straight-line-in-the-jmonkey-engine-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!