Attaching things to models

I saw mention of the md5 stuff having a way to attach objects to model bones and stuff (a pretty old post), but is there a way to do this with any other models. It's preferable if there is a way to do it based on a joint name or something similar stored in the model. I'm even willing to go with editting the xml of a converted model and adding something to the file if necessary. Does anyone have a simple solution to this problem. The simplest way I can imagine without some sort of direct support is to keep a seperate text file with the models that tells my game where important things are (which isn't all together bad, but not ideal).

Likewise dan, also think it is an important feature. It seems as if this is a basic requirement in effective playable games.



This will allow changing of guns - where by the gun is defined in its own model.

This will allow changing of armour - adding a shield or wearing a suit of armour. The armour may vary, may just be a helmet or a breastplate or just leg protection, or it may be a full suit. Either way, the helmet, breastplate are separate models.



This should allow for the updating of the texture of an individual model. If a shield is powered maybe it should bloom, if it is almost worn out it should maybe flash blue

Unfortunately I don't have time to test this, though hopefully by the weekend I'll be able to (got a few more steps to take in my code before I'm here) but it seems to me that as long as I know the node name, I should be able to drill down to that node and attach a node to it, and it will hopefully stay with the node I attach it to. This may only work because of how I made my model and the fact that the converter set it up with a joint controller (ms3d model… he's got a few blocks for parts and a few spheres for joints… a solid mesh might not be so nicely seperated).



This seems so simple that I know there must be a reason no one else posts this when the attaching things to models question comes up (is it so obvious everyone just knows, or is everyone else using different model loaders to convert their models).

is this still the way to go on this.



Or, is there an alternative way to do it.

Hmmm, I wonder if it would be beneficial to have a special Node in jME that can be defined for models that take "attachments". Like a soldier who takes a gun model, a ship who takes a turret or rocket, etc.  This might make it a little easier for people that are trying to make games configurable…

I don't know how animations work so I could (as always) be talking rubbish.



But wouldn't it be better to create a controller that keeps a regular Node in sync with a model Bone.  Then you could obviously just attach anything to the Node like any other Node in the scene.

My trouble is that i know little about models.



Have had a play with loading a model, finding the name of one of its children ( group in milkshake ) and attaching another model to it. It works fine if the attached model was built at the origin ( 0,0,0 ).



Just wondering about skin and welds and wether replacing nodes within the model might break the skin … any expert modellers available to comment

After a model loads, any child nodes do not have sensible local translations ( unless its something to do with the model )



The red wall is a group within the model, it can be accessed as a child by getting it as a node using the name. I would expect this wall to have a local translation of approximately where it looks on the screen ( half way on the left side of the building ).









The following code loads the model and looks at the wall, it also tries to attach an object to the wall. The local translations and world translations printed from the code are below



try {

I think you're seeing the same issue I had when loading my level model and replacing named placeholder cubes with other models. The spatial I would get for the named cube would have a local translation of 0,0,0 just like yours. What I found was that the vertices on the cube were in relation to the entire level model's center. I'm still working with our 3D guy to see what we can do in Blender, but for now I just take an average of all the mesh vertices. Here's the code I use to get an estimated local translation:



public static Vector3f getVertexAverage(TriMesh triMesh) {
   Vector3f[] triVertices = new Vector3f[3];
   Vector3f averagePoint = new Vector3f();
   int triCount = triMesh.getTotalTriangles();
   for (int i = 0; i < triCount; i++) {
      triMesh.getTriangle(i, triVertices);
      averagePoint.addLocal(triVertices[0]).addLocal(triVertices[1].addLocal(triVertices[2]));
   }
   averagePoint.divideLocal(triCount * 3);
   averagePoint.addLocal(triMesh.getLocalTranslation());
   return averagePoint;
}



Try adding this line to your System.outs:


if (wall instanceof TriMesh) {
   System.out.println("wall estimated Local " + getVertexAverage((TriMesh) wall));
}



For the hell of it, here's my node searching code:


public static void findNodes(Spatial parent, String nameMask, List<Spatial> results) {
   boolean endsWith = nameMask.startsWith("*");
   boolean startsWith = nameMask.endsWith("*");
   nameMask = nameMask.substring(endsWith ? 1 : 0, startsWith ? nameMask.length() - 1 : nameMask.length());
   findNodes(parent, nameMask, startsWith, endsWith, results);
}

public static void findNodes(Spatial parent, String nameMask, boolean startsWith, boolean endsWith,
      List<Spatial> results) {
   String parentName = parent.getName();
   if (parentName != null) {
      parentName = parentName.toLowerCase();
      if (startsWith && parentName.startsWith(nameMask)) {
         results.add(parent);
      } else if (endsWith && parentName.endsWith(nameMask)) {
         results.add(parent);
      } else if (parentName.equals(nameMask)) {
         results.add(parent);
      }
   }
   if (parent instanceof Node) {
      for (Spatial child : ((Node) parent).getChildren()) {
         findNodes(child, nameMask, startsWith, endsWith, results);
      }
   }
}



Standard disclaimer: I'm a JME and game dev noob, use my code at your own risk ;)