Placing a Spatial randomly at a model's vertex [SOLVED]

Hi there.



I am doing a game in which the player can collect blocks (RoundedBoxes) that lie around. Each block should be placed at his model, so, if he collects enough of them he would have an armor of blocks around him (which protects him).



This is the idea. Now my player can choose between being a rolling ball and a fighting human (and some other future things). When I programmed the ball, everything worked fine with the code below. But now I am using the ninja-mesh from pyro (a ms3d-file) and with this the placing of the blocks doesn't work anymore. It seems that the blocks are placed at some slim box which is attached to the model's basis and falls down to the ground when I move my player.



I don't know why. Here is my code for placing the blocks, working fine for the ball (a Sphere):


Spatial newBlock = node.getChild("stone");
newBlock.setLocalScale(node.getLocalScale().clone());
blocks.add(newBlock);         
this.node.attachChild(newBlock);
         
Node s = currentForm.getDisplayShape();         
Vector3f[] vecs = ((TriMesh) s.getChild(0)).getMeshAsTrianglesVertices(null);
Random rand = new Random();
int i = rand.nextInt(vecs.length - 1);            
Vector3f vector = vecs[i];         
newBlock.setLocalTranslation(vector);
newBlock.setName("player");
         
game.getWorldNode().detachChild(node);
node.delete();



The DisplayShape simply is a Node which I create when I load the model (copied from the TestFireMilk):


displayShape = new Node();
      
MilkToJme converter=new MilkToJme();
URL MSFile=TestFireMilk.class.getClassLoader().getResource("ressources/models/ninja.ms3d");
ByteArrayOutputStream BO = new ByteArrayOutputStream();

try {
    converter.convert(MSFile.openStream(),BO);
} catch (IOException e) {
    System.exit(0);
}
         
try {
     displayShape = (Node) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
} catch (IOException e) {
     //logger.info("darn exceptions:" + e.getMessage());
}



Here are some screenshots, so I hope you better understand what I meant saying "a slim box attached to the model's basis"....



This is the ball, everything works as I wanted.



A strange slim box, rotating and falling down when I move my player....

Okay, now I know why that box is rotating and falling to the side: I attached the RoundedBoxes to the wrong node. Nevertheless the positions where the RoundedBoxes are set to are obviously still wrong…

its hard to see whats wrong.

Are the blocks too far outside the model?



I'd use small spheres to test your method of attaching the blocks to your human.

That way you see better what location is returned by getMeshAsTrianglesVertices()

That was a nice hint!



Now I see the following:









There is no strange box at all. Seems that simply the triangle’s positions are not updated after I rescale and rotate the model. What I also have in mind is that they are not updated when the model is animated, because I animated it and the positions didn’t change while the model moved.



Is there any update-method or recalc-method I don’t know yet to update the triangles in every cycle or similar?



BTW: Thanks for your help, Core-Dump!


Are you using this ParticleMesh feature that Jme provides ? (not sure it's called like that though)

Cause according to what I saw in the demos, the particles follow the vertices even when it's animated.

hehe good work, hmm updateGeometricState() should do it i think.



Maybe you even need to multiply the vertex location with the local scale and translation to get the correct position, but i don't know for sure.

Thanks for the ideas!



The only thing is: None of them worked properly. updateGeometricState() doesn't do anything nor changes anything, even if I call it in the update-Method.



Next I multiplied the vertices with the scale and the scale-problem seems to be solved by that. But the spheres are still rotated about 90

Did you rotate the model 90

Did you rotate the model 90

Ha! I think I got it!!







The idea for the solution came from orelero’s guess to use a ParticleSystem. My idea was: If ParticleSystem knows how to attach particles at the right vector, it has to get the information I need. So I looked into the code and found the localToWorld()-method of the Spatial-class.



The code I used in the test-class now looks like this:



private void manyVertices(boolean rotScal) {

loadModel(rotScal);

Triangle[] vecs = ((TriMesh) displayShape.getChild(0)).getMeshAsTriangles(null);
      
    for (int i = 0; i < vecs.length; i++) {
                          
       Vector3f vector = new Vector3f();
       ((TriMesh) displayShape.getChild(0)).localToWorld(vecs[i].getCenter(), vector);         
         
       attachSphere(vector, false);
    }

}



Where the boolean rotScal just is a switch to turn on/off rotation and scalation of the model. loadModel() loads the model and stores it into the Node displayShape. attachSphere just puts a green Sphere to the given vector. You can ignore the  boolean (false) in the call - it's just another switch.

Cool!

I'll try out to attach the boxes now properly. First I need to restructure the architecture of my player-node but afterwards I'll tell if everything works fine.

Thanks to both of you!


Here's a little EDIT:

If you want to make the whole thing work with an animated model, you have to update the coords of the Spheres (or whatever should be attached) in the update-method f.e.. I made a HashMap now where I stored the Vertex' index and the Sphere. Works very well:


for (Entry<Sphere, Integer> e : spheres.entrySet()) {         
   ((TriMesh) displayShape.getChild(0)).localToWorld(
         vecs[e.getValue()].getCenter(), e.getKey().getLocalTranslation());                               
}

cool, glad you figured it out.

thats some cool armor :slight_smile: