Hello all,

I’m working on generating a strip to show a path. Each pair of points connects with the next pair with quads.

I am having problems ordering the vertex so that all Quads are correctly generated and ordered to appear when you look from above.

But I’m finding this very hard. It works for some situations and not for others.

I made a MWE to ask you to take a look:

[java]

import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.VertexBuffer.Format;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.scene.VertexBuffer.Usage;

import com.jme3.scene.control.LodControl;

import com.jme3.scene.debug.Arrow;

import com.jme3.util.BufferUtils;

import java.util.ArrayList;

/** Sample 1 - how to get started with the most simple JME 3 application.

- Display a blue 3D cube and view from all sides by

- moving the mouse and pressing the WASD keys. */

public class LOD extends SimpleApplication {

public static void main(String[] args) {

LOD app = new LOD();

app.start(); // start the game

}

@Override

public void simpleInitApp() {

createStripNewDataStruct();

attachCoordinateAxes(new Vector3f(0, 0, 0));

}

private boolean createStripNewDataStruct() {

final int vertNumber = 10;

Vector3f[] finalVertices = new Vector3f[vertNumber];

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

finalVertices[1] = new Vector3f(1, 0, 0);

finalVertices[2] = new Vector3f(2, 0, 0);

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

finalVertices[4] = new Vector3f(4, 0, 0);

finalVertices[5] = new Vector3f(0, 0, 1);

finalVertices[6] = new Vector3f(1, 0, 1);

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

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

finalVertices[9] = new Vector3f(4, 0, 1);

final int triNumberAllVertex = 8;

int orderAllVertex[] = new int[triNumberAllVertex * 3];

Vector3f pointA[] = new Vector3f[2];

Vector3f pointB[] = new Vector3f[2];

ArrayList<int[]> vertexIndexUpDown;

// all the vertex

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

pointA[0] = finalVertices[v];

pointA[1] = finalVertices[v + 5];

pointB[0] = finalVertices[v + 1];

pointB[1] = finalVertices[v + 6];

vertexIndexUpDown = calcVertexOrder(pointA, pointB);

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

switch (vertexIndexUpDown.get(0)*) {*

case 0:

orderAllVertex*= v;*

break;

case 1:

orderAllVertex*= v + 5;*

break;

case 2:

orderAllVertex*= v + 1;*

break;

case 3:

orderAllVertex*= v + 6;*

break;

}

}

}

createMesh(finalVertices, orderAllVertex, “upside”, ColorRGBA.Yellow, null);

return true;

}

protected Geometry createMesh(Vector3f[] vertices, int[] vertexIndex, String meshName, ColorRGBA color,

VertexBuffer[] lod) {

Material mat;

Geometry geom;

Mesh mesh = new Mesh();

// For downside

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

mesh.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(vertexIndex));

mesh.updateBound();

geom = new Geometry(meshName, mesh);

if (lod != null) {

mesh.setLodLevels(lod);

LodControl lodControl = new LodControl();

lodControl.setDistTolerance(20f);

geom.addControl(lodControl);

}

mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.getAdditionalRenderState().setWireframe(true);

mat.setColor(“Color”, ColorRGBA.Red);

geom.setMaterial(mat);

rootNode.attachChild(geom);

return geom;

}

private ArrayList<int[]> calcVertexOrder(Vector3f wingsA[], Vector3f wingsB[]) {

Vector3f[] currVertices = new Vector3f[4];

// Set the current array with the wing points of this and the past point

currVertices[0] = wingsA[0];

currVertices[1] = wingsA[1];

currVertices[2] = wingsB[0];

currVertices[3] = wingsB[1];;

// Calculate how to put them to create one mesh clockwise and another counter clockwise

return orderVertexIndexes(currVertices);

}

private ArrayList<int[]> orderVertexIndexes(Vector3f[] vertices) {

boolean shortest12 = is12ShortestThan03(vertices);

int common2ndWingPDown, common1stWingPDown, opposite2ndWingPDown, opposite1stWingPDown;

opposite1stWingPDown = opposite2ndWingPDown = common1stWingPDown = common2ndWingPDown = -1;

if (shortest12){

common2ndWingPDown = 2;

opposite2ndWingPDown = 3;

common1stWingPDown = 1;

opposite1stWingPDown = 0;

}else{ // shortest

common2ndWingPDown = 3;

opposite2ndWingPDown = 2;

common1stWingPDown = 0;

opposite1stWingPDown = 1;

}

int[] indexesDown = new int[6];

int[] indexesUp = new int[6];

// First triangle

boolean isCCW_Down = isCounterClock(vertices[opposite1stWingPDown], vertices[common1stWingPDown], vertices[common2ndWingPDown]);

indexesDown[0] = opposite1stWingPDown;

indexesUp[0] = opposite1stWingPDown;

if (isCCW_Down) {

indexesDown[1]=common1stWingPDown;

indexesDown[2]=common2ndWingPDown;

// Second triangle

indexesDown[3] = common2ndWingPDown;

indexesDown[4] = common1stWingPDown;

indexesDown[5] = opposite2ndWingPDown;

// - Up

indexesUp[1] = common2ndWingPDown;

indexesUp[2] = common1stWingPDown;

// Second triangle

indexesUp[3] = common1stWingPDown;

indexesUp[4] = common2ndWingPDown;

indexesUp[5] = opposite2ndWingPDown;

}

else {

indexesDown[1]=common2ndWingPDown;

indexesDown[2]=common1stWingPDown;

// Second triangle

indexesDown[3] = common1stWingPDown;

indexesDown[4] = common2ndWingPDown;

indexesDown[5] = opposite2ndWingPDown;

// - Up

indexesUp[1] = common1stWingPDown;

indexesUp[2] = common2ndWingPDown;

// Second triangle

indexesUp[3] = common2ndWingPDown;

indexesUp[4] = common1stWingPDown;

indexesUp[5] = opposite2ndWingPDown;

}

ArrayList<int[]> vertexIndexUpDown = new ArrayList<int[]>(2);

vertexIndexUpDown.add(0, indexesUp);

vertexIndexUpDown.add(1, indexesDown);

return vertexIndexUpDown;

}

private boolean isCounterClock(Vector3f p1, Vector3f p2, Vector3f p3) {

Vector3f normal = FastMath.computeNormal(p1, p2, p3);

// the normal vector for the downwards face must always have negative y

if (normal.y <= 0f) {

return true;

} else {

return false;

}

}

private boolean is12ShortestThan03(Vector3f[] vertices){

float distances[] = new float[2];

distances[0] = vertices[1].distance(vertices[2]); // distBC

distances[1] = vertices[0].distance(vertices[3]); // distAD

if(distances[0] > distances [1]){

return false;

}

else{

return true;

}

}

protected void attachCoordinateAxes(Vector3f pos) {

Arrow arrow = new Arrow(Vector3f.UNIT_X.multLocal(10));

arrow.setLineWidth(4); // make arrow thicker

putShape(arrow, ColorRGBA.Red).setLocalTranslation(pos);

arrow = new Arrow(Vector3f.UNIT_Y.multLocal(10));

arrow.setLineWidth(4); // make arrow thicker

putShape(arrow, ColorRGBA.Green).setLocalTranslation(pos);

arrow = new Arrow(Vector3f.UNIT_Z.multLocal(10));

arrow.setLineWidth(4); // make arrow thicker

putShape(arrow, ColorRGBA.Blue).setLocalTranslation(pos);

}

protected Geometry putShape(Mesh shape, ColorRGBA color) {

Geometry g = new Geometry(“coordinate axis”, shape);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.getAdditionalRenderState().setWireframe(true);

mat.setColor(“Color”, color);

g.setMaterial(mat);

rootNode.attachChild(g);

return g;

}

}[/java]

This is what I get: