Cant copy mesh. Jme is Bugged

[java]

for (Geometry child : childrenToAdd)

{

Mesh childMesh = child.getMesh();

Mesh childMeshwithoutAnimation = new MeshData(childMesh).createMesh();



node[numModels].attachChild(new Geometry("a node", childMesh));

}[/java]



if i use ChildMesh it has animation normally, if i use childMeshwithoutAnimation it loses all animation.

How come a mesh losses all its animation when it has the exactly the same Type.Position, Type.Normal, Type.Index,Type.BindPosePosition, Type.BindPoseNormal, Type.BoneWeight, Type.BoneIndex, Type.TexCoord, Type.TexCoord2, Type.TexCoord3, Type.TexCoord4, Type.TexCoord5, Type.TexCoord6, Type.TexCoord7, Type.TexCoord8 ?





Its like saying 1 != 1 .



[java]VertexBuffer bn = childMesh.getBuffer(Type.Binormal);

VertexBuffer c = childMesh.getBuffer(Type.Color);

VertexBuffer i = childMesh.getBuffer(Type.InterleavedData);

VertexBuffer ma = childMesh.getBuffer(Type.MiscAttrib);

VertexBuffer s = childMesh.getBuffer(Type.Size);

VertexBuffer ta = childMesh.getBuffer(Type.Tangent);



System.out.println(bn);

System.out.println©;

System.out.println(i);

System.out.println(ma);

System.out.println(s);

System.out.println(ta);[/java]

It prints null, which means that childMesh has all other buffers null, so childMesh == childMeshwithoutAnimation (theoritically).



So how come they are equal and yet it has no animation ?



In a desperate last chance to make sure they are the same i copy every possible variable they have :

[java]

for (Geometry child : childrenToAdd)

{

Mesh childMesh = child.getMesh();

Mesh childMeshwithoutAnimation = new MeshData(childMesh).createMesh();



childMeshwithoutAnimation.setElementLengths(childMesh.getElementLengths());

childMeshwithoutAnimation.setId(childMesh.getId());

childMeshwithoutAnimation.setLineWidth(childMesh.getLineWidth());

childMeshwithoutAnimation.setMaxNumWeights(childMesh.getMaxNumWeights());

childMeshwithoutAnimation.setMode(childMesh.getMode());

childMeshwithoutAnimation.setModeStart(childMesh.getModeStart());

childMeshwithoutAnimation.setPointSize(childMeshwithoutAnimation.getPointSize());



node[numModels].attachChild(new Geometry("a node", childMeshwithoutAnimation));

}

[/java]



childMeshwithoutAnimation still doesnt have animation.



does mesh class have any hidden private variables that we monkey users cannot access ?

Because you need an AnimControl and a SkeletonControl on the new geometry you create.



try to use the geom.clone() method.

I have animControl in the parent node.

In both cases (childMesh and childMeshwithoutAnimation ) i construct a new empty geometry that contains the specified mesh. And childMesh has animation even though it is in a new geometry, so geometry class is not the problem but the Mesh class.

[java]

for (Geometry child : childrenToAdd)

{

Mesh childMesh = child.getMesh(); //this has animation

Mesh childMeshwithoutAnimation = new Mesh();

Mesh childMeshwithAnimation = childMesh.clone();//copies private variables because of clone = it has animation.

MeshData childData = new MeshData(childMesh);

childData.save( childMeshwithoutAnimation ); //saves all buffers to the new mesh.

childData.save( childMeshwithAnimation );

node[numModels].attachChild(new Geometry(“a node”, childMeshwithAnimation));

}

[/java]

Note that childMeshwithAnimation has animation now, so the problems is that Mesh class has private variables that we cannot copy with set methods, and have to use clone() which is ungly.

Also i didnt use the following methods at all ( generateBindPose, prepareForAnim ) because they throw exception so i guess we arent supposed to touch them ?

If i use prepareForAnim it throws “java.lang.IllegalArgumentException: FloatBuffer is not direct”

Why clone is ugly? it’s made for this exact purpose.

  1. I used clone, to show you that jme mesh class has variables that contain data but it doesnt allow us to copy / get them.
  2. i need to copy them without clone, because i am using custom meshes, and in custom meshes we usually do

    a) Mesh mesh = new Mesh();

    b) we set its buffers.

    c) its ready (but now it has no animation).



    Yes i could have done Mesh mesh = something.clone(); but it seems ungly in custom meshes because :
  3. what if it undergoes a complex transformation and makes it different than starting mesh.
  4. it seems like an ungly hack to get it to work for the specified case and not solving the general problem.
  5. Are all custom meshes supposed to have no animation because of a stupid private boolean variable that controls if animation is played ?

Meshes do not contain animation data, I don’t quite get what you are talking about?

i realise that @nehon must be right. I guess animations data arent stored in the mesh but in the SkeletonControl/ AnimControl. I have to enable the AnimControl / SkeletonControl for the new generated custom mesh. How do i do that ?

[java]

Node node = (Node)assetManager.loadModel(“Models/Sinbad/Sinbad.mesh.xml”);

SkeletonControl skeleton = node.getControl(SkeletonControl.class);

AnimControl animation = node.getControl(AnimControl.class);



//apply symmetry modifier to all model parts.

for(Spatial child : node.getChildren())

{

Geometry geom = (Geometry)child;

Mesh mesh = geom.getMesh();

MeshData data = new MeshData(mesh).createSymmetricMesh(Vector3f.ZERO, Vector3f.UNIT_Y, 0.1f);

mesh = data.createMesh();

geom.setMesh(mesh); //BUG : each mesh loses animation.

}

[/java]

i tried the following :

  1. geom.addControl(animation);

    result : java.lang.IllegalStateException: This control has already been added to a Spatial

    at com.jme3.scene.control.AbstractControl.setSpatial(AbstractControl.java:59)

Try cloneForSpatial… What is it you want to do anyway? Just clone the friggin model or load it twice from the assetmanager, this way its cloned automatically.

i load the model, the apply symmetry, but then it stops playing animations. Because i save all created buffers in a new mesh(). So i need to activate the skeletonControl so it works with the new created mesh.



How do i use cloneForSpatial ? i tried this :



[java]

animation.cloneForSpatial(geom);

skeleton.cloneForSpatial(geom);[/java]



java.lang.ClassCastException: com.jme3.scene.Geometry cannot be cast to com.jme3.scene.Node

at com.jme3.animation.SkeletonControl.cloneForSpatial(SkeletonControl.java:192)

at jme3test.TestSymmetry.simpleInitApp(TestSymmetry.java:48)

the skeleton control has wrong Mesh[] targets, because the meshes were modified.



[java]

SkeletonControl skeleton = node.getControl(SkeletonControl.class);

AnimControl animation = node.getControl(AnimControl.class);



node.removeControl(animation);

node.addControl(animation);

node.removeControl(skeleton);

node.addControl(skeleton);[/java]



gg, no matter what i do it hates me :

java.lang.IllegalStateException: Max weights per vert is incorrectly set!

at com.jme3.animation.SkeletonControl.softwareSkinUpdate(SkeletonControl.java:274)

at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:152)

at com.jme3.scene.control.AbstractControl.render(AbstractControl.java:93)

Because clone() is a shallow clone, it cannot be used for animation as each mesh has to be animated individually. Use cloneForAnim() instead

clone worked when i did no operations / transformations on the mesh, (Unmodified).

I tried doing some transformations after clone(), here are the results :

clone() : original mesh and all its instances are destroyed, I am seeing only half mesh (the symmetric) which plays a move hand animation, however because of incorrect skinning the hand is distorted.

cloneForAnim() : original mesh is moved at the position of the symmetric mesh, then the symmetric half mesh plays the distorted animation exactly like in clone(). The original model loses his animation.

deepClone(): Exact same effects as new mesh(). Original model has animation (correct), symmetric model has no animation.

Which means that clone doesnt solve the problem. The problem is that skeleton control stores Mesh[] targets inside it which are outdated (e.g not updated after my transformations).

With the latest version of jME3 you can refresh the target list by detaching and then attaching the SkeletonControl

So, to be sure i understand : you clone or copy or w/e the model then you apply some kind of symmetry on the mesh. right?



In that case i guess you’ll have to apply the symmetry to the skeleton and the animData too

@Momoko_Fan i updated jme and when i run this :

[java]

node.removeControl(skeletonControl);

node.addControl(skeletonControl);[/java]

I get java.lang.IllegalStateException: Max weights per vert is incorrectly set!

at com.jme3.animation.SkeletonControl.softwareSkinUpdate(SkeletonControl.java:274)

at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:152)

And i have no idea what that means.

@nehon :

I am using this : http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/forum/topic/symmetry-mirror-modifer-uv-transformations/

You proposed to apply the symmetry to the skeleton / animData too. I exported from 3d studio max a symmetric skeleton / animData and the symmetric model doesnt move at all.

Propably because its not in SkeletonControl’s Mesh[] targets variable.





Also if i use :

mesh.setMaxNumWeights(geom.getMesh().getMaxNumWeights());

Instead of Max weights per vert is incorrectly set! i get :

java.lang.ArrayIndexOutOfBoundsException: 88

at com.jme3.animation.SkeletonControl.softwareSkinUpdate(SkeletonControl.java:329)

at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:152)

at com.jme3.scene.control.AbstractControl.render(AbstractControl.java:93)

at com.jme3.scene.Spatial.runControlRender(Spatial.java:536)