I feel like the mesh class could be more convenient to work with if a simple utility method was added to it. I’ve created a class below that extends mesh just to show what I mean, but it makes life a lot simpler when dealing with mesh creation; arrays vs lists, Buffers, and all the little niggling things that are annoying - like creating a List<Integer>
for triangles because you can’t use primitives in a collection, having to convert it to a int[] array, etc… All the little annoyances that can be taken care of with boilerplate code.
JmeMesh mesh = new JmeMesh();
// set the buffer for any type using collections or arrays, primitives or wrapped primitives.
List<Vector3f> vertsList....
Vector3f[] normArray....
List<Integer> triangles...
mesh.set(Type.Position, vertsList);
mesh.set(Type.Normal, normals);
mesh.set(Type.Index, triangles);
// and so on...
package com.jayfella.pixels.grid;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.util.BufferUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
public class JmeMesh extends Mesh {
public JmeMesh() {
super();
}
public void set(VertexBuffer.Type type, Collection<?> inputValues) {
set(type, inputValues.toArray());
}
public void set(VertexBuffer.Type type, Object[] inputValues) {
set(type, null, inputValues);
}
public void set(VertexBuffer.Type type, Integer components, Object[] inputValues) {
if (inputValues == null || inputValues.length == 0) {
clearBuffer(type);
return;
}
if (inputValues.getClass().getComponentType() == float.class || inputValues.getClass().getComponentType() == Float.class) {
FloatBuffer fb = BufferUtils.createFloatBuffer(inputValues.length);
for (Object inputValue : inputValues) {
fb.put( (float) inputValue );
}
int c = (components == null ? 1 : components);
setBuffer(type, c, fb);
}
if (inputValues.getClass().getComponentType() == int.class || inputValues.getClass().getComponentType() == Integer.class) {
IntBuffer ib = BufferUtils.createIntBuffer(inputValues.length);
for (Object inputValue : inputValues) {
ib.put((int) inputValue);
}
int c = type == VertexBuffer.Type.Index
? 3
: (components == null ? 3 : components);
setBuffer(type, c, ib);
}
else if (inputValues.getClass().getComponentType() == Vector2f.class) {
FloatBuffer fb = BufferUtils.createFloatBuffer(inputValues.length * 2);
for (Object inputValue : inputValues) {
fb.put(((Vector2f)inputValue).x);
fb.put(((Vector2f)inputValue).y);
}
setBuffer(type, 2, fb);
}
else if (inputValues.getClass().getComponentType() == Vector3f.class) {
FloatBuffer fb = BufferUtils.createFloatBuffer(inputValues.length * 3);
for (Object inputValue : inputValues) {
fb.put(((Vector3f)inputValue).x);
fb.put(((Vector3f)inputValue).y);
fb.put(((Vector3f)inputValue).z);
}
setBuffer(type, 3, fb);
}
else if (inputValues.getClass().getComponentType() == Vector4f.class) {
FloatBuffer fb = BufferUtils.createFloatBuffer(inputValues.length * 4);
for (Object inputValue : inputValues) {
fb.put(((Vector4f)inputValue).x);
fb.put(((Vector4f)inputValue).y);
fb.put(((Vector4f)inputValue).z);
fb.put(((Vector4f)inputValue).w);
}
setBuffer(type, 4, fb);
}
// if we update the positions of the vertices, we also need to update the bounds of the mesh.
if (type == VertexBuffer.Type.Position) {
updateBound();
}
}
}