So, I modified GeometryBatch. I added the addMeshGeometry methods, which read the translation and rotation from the mesh itself (and allow additional Transformations) and I added the possibility to perform an arbitrary "Transformation", which can be "everything" (translation, rotation, scalation and even nonaffine transformation). The code is not really tested, so be careful…
import com.jme.math.Quaternion;
import com.jme.scene.TriMesh;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ByteBuffer;
import com.jme.math.Vector3f;
import com.jme.util.geom.BufferUtils;
import com.jme.bounding.BoundingBox;
/**
*
* @author mike
*/
public class GeometryBatch extends TriMesh {
/** Do not use, for internal use only */
public GeometryBatch() {
FloatBuffer vertices = BufferUtils.createFloatBuffer(0);
FloatBuffer normal = BufferUtils.createFloatBuffer(0);
FloatBuffer color = null;
FloatBuffer texture = BufferUtils.createFloatBuffer(0);
IntBuffer indices = BufferUtils.createIntBuffer(0);
reconstruct(vertices, normal, color, texture, indices);
this.setModelBound(new BoundingBox());
updateModelBound();
}
public GeometryBatch(String name) {
super(name);
FloatBuffer vertices = BufferUtils.createFloatBuffer(0);
FloatBuffer normal = BufferUtils.createFloatBuffer(0);
FloatBuffer color = null;
FloatBuffer texture = BufferUtils.createFloatBuffer(0);
IntBuffer indices = BufferUtils.createIntBuffer(0);
reconstruct(vertices, normal, color, texture, indices);
this.setModelBound(new BoundingBox());
updateModelBound();
}
public static GeometryBatch create(String name, TriMesh mesh) {
return new GeometryBatch(name, mesh);
}
/** Creates a new instance of GeometryBatch */
public GeometryBatch(String name, TriMesh mesh) {
super(name);
//System.out.println("Adding mesh " + mesh.toString());
FloatBuffer vertices = BufferUtils.clone(mesh.getVertexBuffer(0));
FloatBuffer normal = BufferUtils.clone(mesh.getNormalBuffer(0));
FloatBuffer color = BufferUtils.clone(mesh.getColorBuffer(0));
FloatBuffer texture = BufferUtils.clone(mesh.getTextureBuffer(0,0));
IntBuffer indices = BufferUtils.clone(mesh.getIndexBuffer(0));
reconstruct(vertices, normal, color, texture, indices);
this.setModelBound(new BoundingBox());
updateModelBound();
}
public static void dumpFloatBuffer(FloatBuffer buff, String title) {
System.out.println("********** Start FloatBuffer " + title);
int cap = buff.capacity();
buff.rewind();
System.out.println();
for (int ii=0; ii<cap; ii++) {
System.out.println(buff.get());
}
System.out.println();
System.out.println("********** End FloatBuffer **********");
buff.rewind();
}
public static void dumpIntBuffer(IntBuffer buff, String title) {
System.out.println("********** Start IntBuffer " + title);
int cap = buff.capacity();
buff.rewind();
System.out.println();
for (int ii=0; ii<cap; ii++) {
System.out.println(Integer.toString(ii) + " " + Integer.toString(buff.get()));
}
System.out.println();
System.out.println("********** End IntBuffer **********");
buff.rewind();
}
public void addMeshGeometry(TriMesh mesh) {
addGeometry(mesh, Transformation.getRotationTranslation(mesh.getLocalRotation(), mesh.getLocalTranslation()));
}
public void addMeshGeometry(TriMesh mesh, Vector3f translation) {
addGeometry(mesh, Transformation.getRotationTranslation(mesh.getLocalRotation(),
mesh.getLocalTranslation().add(translation)));
}
public void addMeshGeometry(TriMesh mesh, Transformation trans) {
addGeometry(mesh, Transformation.getTransformationChain(
Transformation.getRotationTranslation(mesh.getLocalRotation(), mesh.getLocalTranslation()), trans));
}
public void addGeometry(TriMesh mesh, Vector3f translation) {
addGeometry(mesh, Transformation.getTranslation(translation));
}
public void addGeometry(TriMesh mesh, Transformation trans) {
// Append the indices.
int total = this.getIndexBuffer(0).capacity() + mesh.getIndexBuffer(0).capacity();
IntBuffer indices = BufferUtils.createIntBuffer(total);
IntBuffer buff = this.getIndexBuffer(0);
buff.rewind();
indices.put(buff);
int extra = this.getVertexBuffer(0).capacity() / 3;
buff = mesh.getIndexBuffer(0);
buff.rewind();
for (int ii=0; ii<buff.capacity(); ii++) {
indices.put(buff.get() + extra);
}
// Append the normals.
total = this.getNormalBuffer(0).capacity() + mesh.getNormalBuffer(0).capacity();
FloatBuffer normal = BufferUtils.createFloatBuffer(total);
FloatBuffer buff2 = this.getNormalBuffer(0);
buff2.rewind();
normal.put(buff2);
buff2 = mesh.getNormalBuffer(0);
buff2.rewind();
normal.put(buff2);
// Append the texture coords.
total = this.getTextureBuffer(0,0).capacity() +
mesh.getTextureBuffer(0,0).capacity();
FloatBuffer texture = BufferUtils.createFloatBuffer(total);
buff2 = this.getTextureBuffer(0,0);
buff2.rewind();
texture.put(buff2);
buff2 = mesh.getTextureBuffer(0,0);
buff2.rewind();
texture.put(buff2);
// Take a temp copy of the vertices and rotate / translate them.
FloatBuffer temp = BufferUtils.clone(mesh.getVertexBuffer(0));
int count = temp.capacity() / 3;
Vector3f tempVec = new Vector3f();
for (int ii=0; ii < count; ii++) {
BufferUtils.populateFromBuffer(tempVec, temp, ii);
trans.transform(tempVec);
BufferUtils.setInBuffer(tempVec, temp, ii);
}
temp.rewind();
// Append the vertices.
total = this.getVertexBuffer(0).capacity() + mesh.getVertexBuffer(0).capacity();
FloatBuffer vertices = BufferUtils.createFloatBuffer(total);
buff2 = this.getVertexBuffer(0);
buff2.rewind();
vertices.put(buff2);
vertices.put(temp);
// Append the colour.
FloatBuffer color = null;
if (this.getColorBuffer(0) != null && mesh.getColorBuffer(0) == null) {
color = BufferUtils.clone(this.getColorBuffer(0));
} else if (mesh.getColorBuffer(0) != null && this.getColorBuffer(0) == null) {
color = BufferUtils.clone(mesh.getColorBuffer(0));
} else if (mesh.getColorBuffer(0) != null && this.getColorBuffer(0) != null) {
total = this.getColorBuffer(0).capacity() + mesh.getColorBuffer(0).capacity();
color = BufferUtils.createColorBuffer(total);
buff2 = this.getColorBuffer(0);
buff2.rewind();
color.put(buff2);
buff2 = mesh.getColorBuffer(0);
buff2.rewind();
color.put(buff2);
}
reconstruct(vertices, normal, color, texture, indices);
updateModelBound();
}
public String toString() {
return super.toString();
}
}
Use the static methods of this class or implement a subclass:
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
/**
*
* @author DGronau
*/
public abstract class Transformation {
abstract public void transform(Vector3f vector);
public static Transformation getIdentity() {
return new Transformation() {
public void transform(Vector3f vector) {}
};
}
public static Transformation getTranslation(final Vector3f translation) {
return new Transformation() {
public void transform(Vector3f vector) {
vector.addLocal(translation);
}
};
}
public static Transformation getRotation(final Quaternion rotation) {
return new Transformation() {
public void transform(Vector3f vector) {
rotation.multLocal(vector);
}
};
}
public static Transformation getRotationTranslation(final Quaternion rotation, final Vector3f translation) {
return new Transformation() {
public void transform(Vector3f vector) {
rotation.multLocal(vector);
vector.addLocal(translation);
}
};
}
public static Transformation getTranslationRotation(final Vector3f translation, final Quaternion rotation) {
return new Transformation() {
public void transform(Vector3f vector) {
vector.addLocal(translation);
rotation.multLocal(vector);
}
};
}
public static Transformation getScale(final Vector3f scale) {
return new Transformation() {
public void transform(Vector3f vector) {
vector.multLocal(scale);
}
};
}
public static Transformation getTransformationChain(final Transformation... transformations) {
return new Transformation() {
public void transform(Vector3f vector) {
for (Transformation transformation : transformations) {
transformation.transform(vector);
}
}
};
}
}