I have another question on what to mean appears to be a bug. But I have a question.
Inside BatchNode class under function “mergeGeometries”. It appears to have a bug from the way I see it. I wanted to make sure.
At the end of the function where it is looping through the vertexBuffer to copy them from the individual Geom to the merge Geom.
It does a check for VertexBuffer.Type.Index, .Position, .Normal and there is an “ELSE” for everything else.
Now the line “inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount);” copies the vertexBuffer from the inBuf to the outBuf but the inBuf “HAS” to be the same size of the Vertices Count. Which means if you want to create your own vertexBuffer and put in your own buffer, since JME forces you to use a predefined vertexBuffer because you can’t use a “Other”, so you have to use a buffer that is not being used to get your own data down to the shader.
But it is forcing you to have your vertexBuffer to have an array that matches the total number of vertices.
WHY DOES IT FORCE THIS?
Why could you not add
int numElements = inBuf.getNumElements();
//Change following line to
inBuf.copyElements(0, outBuf, globalVertIndex, numElements);
This way the vertexBuffer can be anything the user wishes to put into the buffer that they are using for other information.
Am I correct this is an over look of possible usage? Could it be changed to this?
private void mergeGeometries(Mesh outMesh, List<Geometry> geometries) {
int[] compsForBuf = new int[VertexBuffer.Type.values().length];
VertexBuffer.Format[] formatForBuf = new VertexBuffer.Format[compsForBuf.length];
boolean[] normForBuf = new boolean[VertexBuffer.Type.values().length];
int totalVerts = 0;
int totalTris = 0;
int totalLodLevels = 0;
int maxWeights = -1;
Mesh.Mode mode = null;
float lineWidth = 1f;
for (Geometry geom : geometries) {
totalVerts += geom.getVertexCount();
totalTris += geom.getTriangleCount();
totalLodLevels = Math.min(totalLodLevels, geom.getMesh().getNumLodLevels());
if (maxVertCount < geom.getVertexCount()) {
maxVertCount = geom.getVertexCount();
}
Mesh.Mode listMode;
//float listLineWidth = 1f;
int components;
switch (geom.getMesh().getMode()) {
case Points:
listMode = Mesh.Mode.Points;
components = 1;
break;
case LineLoop:
case LineStrip:
case Lines:
listMode = Mesh.Mode.Lines;
//listLineWidth = geom.getMesh().getLineWidth();
components = 2;
break;
case TriangleFan:
case TriangleStrip:
case Triangles:
listMode = Mesh.Mode.Triangles;
components = 3;
break;
default:
throw new UnsupportedOperationException();
}
for (VertexBuffer vb : geom.getMesh().getBufferList().getArray()) {
int currentCompsForBuf = compsForBuf[vb.getBufferType().ordinal()];
if (vb.getBufferType() != VertexBuffer.Type.Index && currentCompsForBuf != 0 && currentCompsForBuf != vb.getNumComponents()) {
throw new UnsupportedOperationException("The geometry " + geom + " buffer " + vb.getBufferType()
+ " has different number of components than the rest of the meshes "
+ "(this: " + vb.getNumComponents() + ", expected: " + currentCompsForBuf + ")");
}
compsForBuf[vb.getBufferType().ordinal()] = vb.getNumComponents();
formatForBuf[vb.getBufferType().ordinal()] = vb.getFormat();
normForBuf[vb.getBufferType().ordinal()] = vb.isNormalized();
}
maxWeights = Math.max(maxWeights, geom.getMesh().getMaxNumWeights());
if (mode != null && mode != listMode) {
throw new UnsupportedOperationException("Cannot combine different"
+ " primitive types: " + mode + " != " + listMode);
}
mode = listMode;
compsForBuf[VertexBuffer.Type.Index.ordinal()] = components;
}
outMesh.setMaxNumWeights(maxWeights);
outMesh.setMode(mode);
//outMesh.setLineWidth(lineWidth);
if (totalVerts >= 65536) {
// Make sure we create an UnsignedInt buffer, so we can fit all of the meshes.
formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedInt;
} else {
formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedShort;
}
// generate output buffers based on retrieved info
for (int i = 0; i < compsForBuf.length; i++) {
if (compsForBuf[i] == 0) {
continue;
}
Buffer data;
if (i == VertexBuffer.Type.Index.ordinal()) {
data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalTris);
} else {
data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalVerts);
}
VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.values()[i]);
vb.setupData(VertexBuffer.Usage.Dynamic, compsForBuf[i], formatForBuf[i], data);
vb.setNormalized(normForBuf[i]);
outMesh.setBuffer(vb);
}
int globalVertIndex = 0;
int globalTriIndex = 0;
for (Geometry geom : geometries) {
Mesh inMesh = geom.getMesh();
if (!isBatch(geom)) {
geom.associateWithGroupNode(this, globalVertIndex);
}
int geomVertCount = inMesh.getVertexCount();
int geomTriCount = inMesh.getTriangleCount();
for (int bufType = 0; bufType < compsForBuf.length; bufType++) {
VertexBuffer inBuf = inMesh.getBuffer(VertexBuffer.Type.values()[bufType]);
VertexBuffer outBuf = outMesh.getBuffer(VertexBuffer.Type.values()[bufType]);
if (outBuf == null) {
continue;
}
if (VertexBuffer.Type.Index.ordinal() == bufType) {
int components = compsForBuf[bufType];
IndexBuffer inIdx = inMesh.getIndicesAsList();
IndexBuffer outIdx = outMesh.getIndexBuffer();
for (int tri = 0; tri < geomTriCount; tri++) {
for (int comp = 0; comp < components; comp++) {
int idx = inIdx.get(tri * components + comp) + globalVertIndex;
outIdx.put((globalTriIndex + tri) * components + comp, idx);
}
}
} else if (VertexBuffer.Type.Position.ordinal() == bufType) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos, 3);
} else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos, compsForBuf[bufType]);
if (VertexBuffer.Type.Tangent.ordinal() == bufType) {
useTangents = true;
}
} else {
if (inBuf == null) {
throw new IllegalArgumentException("Geometry " + geom.getName() + " has no " + outBuf.getBufferType() + " buffer whereas other geoms have. all geometries should have the same types of buffers.\n Try to use GeometryBatchFactory.alignBuffer() on the BatchNode before batching");
} else if (outBuf == null) {
throw new IllegalArgumentException("Geometry " + geom.getName() + " has a " + outBuf.getBufferType() + " buffer whereas other geoms don't. all geometries should have the same types of buffers.\n Try to use GeometryBatchFactory.alignBuffer() on the BatchNode before batching");
} else {
inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount);
}
}
}
globalVertIndex += geomVertCount;
globalTriIndex += geomTriCount;
}
}