Hi!
Ok, here is a test case to change the mesh (not adding, just moving "a" vector).
I thought that change should make the cube look different and also affect physics.
I am new to JME3, so much I cant even make the 2nd cube hit the one below it :(.
(I am using this jME3_08-18-2010.zip on eclipse.)
import java.nio.FloatBuffer;
import com.jme3.app.SimpleBulletApplication;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.nodes.PhysicsNode;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
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.Type;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
public class TestCaseModifyMesh extends SimpleBulletApplication{
Geometry modifyMe;
int iBoxCount = 0;
public static void main (String args[]){
TestCaseModifyMesh tcmm = new TestCaseModifyMesh();
AppSettings settings = new AppSettings(true);
settings.setResolution(320,200);
settings.setFullscreen(false);
//settings.setAudioRenderer(null);
tcmm.setSettings(settings);
tcmm.start();
}
enum eActions {
ModifyMesh
};
@Override
public void simpleInitApp() {
msg("hit space to attempt to modify mesh!");
inputManager.addMapping(eActions.ModifyMesh.toString(),
new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(actionListener, eActions.ModifyMesh.toString());
// static
float fMass = 0; //static objects has mass=0
modifyMe = createBoxAt3DPos(new Vector3f(0,-1,5),fMass);
// falling over, why doesnt work/hit ?
fMass = 1;
createBoxAt3DPos(new Vector3f(0,1,5),fMass);
}
private ActionListener actionListener = new ActionListener() {
public void onAction(String name, boolean keyPressed, float tpf) {
if(!keyPressed){
eActions e = eActions.valueOf(name);
switch(e){
case ModifyMesh: {
int iVectorIndex = 20; //is at top of box, see Box class
Vector3f v3f = getVector(modifyMe, iVectorIndex);
v3f.addLocal(0,1.25f,0); //1.25f arbitrary...
scanGeomSetAllMatchingVectors(modifyMe, iVectorIndex, v3f);
}break;
}
}
}
};
private Geometry createBoxAt3DPos(Vector3f pos, float mass){
iBoxCount++;
float size = 0.5f;
Material matDefault = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
matDefault.setColor("m_Color", ColorRGBA.Gray);
Box box = new Box(Vector3f.ZERO,size,size,size);
Geometry geomBox = new Geometry("Box:"+iBoxCount, box);
geomBox.setMaterial(matDefault);
geomBox.setLocalTranslation(pos);
Vector3f halfExtents = new Vector3f(size,size,size);
PhysicsNode physnodeBox = new PhysicsNode(geomBox, new BoxCollisionShape(halfExtents), mass);
getPhysicsSpace().add(physnodeBox);
rootNode.attachChild(physnodeBox);
physnodeBox.updateGeometricState();
physnodeBox.updateModelBound();
physnodeBox.updatePhysicsState();
return geomBox;
}
private Vector3f getVector(Geometry geom, int iVectorIndex){
VertexBuffer vtbuf = geom.getMesh().getBuffer(Type.Position);
FloatBuffer fbuff = (FloatBuffer)vtbuf.getData();
Vector3f v3f = new Vector3f();
for(int i=0; i<3; i++){
try{
v3f.set(i,fbuff.get((iVectorIndex*3)+i));
}catch(IndexOutOfBoundsException e){
return null; //end of array
}
}
msg("vec="+iVectorIndex+";pos="+v3f);
return v3f;
}
private void scanGeomSetAllMatchingVectors(Geometry geom, int iVectorIndex, Vector3f v3fNewPos){
Mesh mesh = geom.getMesh();
VertexBuffer vtbuf = mesh.getBuffer(Type.Position);
FloatBuffer fbuff = (FloatBuffer)vtbuf.getData();
Vector3f v3fRefVector = getVector(geom, iVectorIndex);
// set matching ones
msg("lim="+fbuff.limit());
msg("cap="+fbuff.capacity());
msg("pos="+fbuff.position());
//msg("arlen="+fbuff.array().length); ???
for(int i2=0; i2<fbuff.limit(); i2++){
Vector3f v3f = getVector(geom, i2);
if(v3f == null)
break; //end of filled up array
if(v3f.equals(v3fRefVector)){
for(int i=0; i<3; i++){
int iFloatPos = (i2*3)+i;
fbuff.put(iFloatPos,v3fNewPos.get(i));
msg("vec="+i2+";axis="+i+";val="+v3fNewPos.get(i)+";valSet="+fbuff.get(iFloatPos));
}
}
}
geom.updateGeometricState();
geom.updateModelBound();
((PhysicsNode)geom.getParent()).updatePhysicsState();
checkVector(geom,iVectorIndex);
}
private void checkVector(Geometry geom, int iVectorIndex){
VertexBuffer vtbuf = geom.getMesh().getBuffer(Type.Position);
FloatBuffer fbuff = (FloatBuffer)vtbuf.getData();
Vector3f v3f = new Vector3f();
for(int i=0; i<3; i++){
v3f.set(i,fbuff.get((iVectorIndex*3)+i));
}
msg("posCheck="+v3f);
}
public static int iDebugLevel = 1;
public static void msg(Object obj){
msg(obj,-1,1);
}
public static void msg(Object obj,int iLevel){
msg(obj,iLevel,1);
}
private static void msg(Object obj,int iLevel,int iIncStack){
StackTraceElement[] ael = Thread.currentThread().getStackTrace();
String methodName = ael[2+iIncStack].getMethodName();
if(iLevel >= iDebugLevel || iLevel == -1)
System.out.println("DEBUG "+methodName+"(): "+obj);
}
}
I am thinking on using JME2 with MetaBalls ScalarField etc. to render the outside mesh.
I think MetaBalls can be ported to JME3, not sure. I need to see if it will work fast enough with my requirements, before doing another step.
Another thought was to make a copy of com.jme3.scene.shape.Sphere and change it in a way that each triangle could be added arbitrarily before creating the mesh (not being a Sphere of course). And also allow modifying in runtime. Too difficult to me yet, this is just a guess anyway.
If someone could explain or point to me a link explaining why nothing happens when I modify the FloatBuffer, would be cool :). I think that if I replace the mesh with the modified one (modified FloatBuffer) and reinitialize the object (or destroy it and create a new one) it will work.
So, my next try will be with MetaBalls code at JME2. And I know it may be slow with the ammount of cubes I plan for it :(. Submeshes may work great tho! (several 5x5x5 or 10x10x10 cubes).