Trying to "attach" a Spatial to a Mesh

Alright, so I’m trying to “attach” a Spatial to a mesh, and by that I mean, and by that I mean I want it to “follow” the primitive it’s “attached” to.

I’m doing this cause I’ve switched from .dae to .md2, and .md2 doesn’t have bones, or joints to attach anything to.

This is what I got so far.

public int getTopSelection(Mesh m){
    	 m.updateWorldBound(true);
    	 int c = m.getMeshData().getPrimitiveCount(0);
    	 double maxHeight = 0;
    	 int selection = 0;
    	 Vector3[][] v3 = new Vector3[c][3];
         for(int s = 0; s < c; s++){
 	        v3[s] = null;
 	        v3[s] = m.getMeshData().getPrimitive(s, 0, v3[s]);
 	        
 	        Vector3 min = new Vector3((float)Math.min((float) Math.min(v3[s][0].getXf(), v3[s][1].getXf()), v3[s][2].getXf()),
 	        		(float)Math.min((float)Math.min(v3[s][0].getYf(), v3[s][1].getYf()), v3[s][2].getYf()),
 	        		(float)Math.min((float)Math.min(v3[s][0].getZf(), v3[s][1].getZf()), v3[s][2].getZf()));
 	        
 	        Vector3 max = new Vector3((float) Math.max((float)Math.max(v3[s][0].getXf(), v3[s][1].getXf()), v3[s][2].getXf()),
 	        		(float)Math.max((float)Math.max(v3[s][0].getYf(), v3[s][1].getYf()), v3[s][2].getYf()),
 	        		(float)Math.max((float)Math.max(v3[s][0].getZf(), v3[s][1].getZf()), v3[s][2].getZf()));
 	        
 	        if(max.getY() < maxHeight){
 	        	maxHeight = max.getY();
 	        	selection = s;
 	        }	
         }
 
         return selection;
    	 
    }
    
    
    public Vector3[] getPrimitive(Mesh m, int selection){
	   	m.updateWorldBound(true);
	   	 
		
	   	Vector3[] v3 = new Vector3[3]; 
	   	v3 = m.getMeshData().getPrimitive(selection, 0, v3); 
	   	
	   	Vector3 min = new Vector3((float)Math.min((float) Math.min(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
	    		(float)Math.min((float)Math.min(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
	    		(float)Math.min((float)Math.min(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    
		Vector3 max = new Vector3((float) Math.max((float)Math.max(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
			(float)Math.max((float)Math.max(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
			(float)Math.max((float)Math.max(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    
	    Vector3 middle = new Vector3(
	    (max.getX() - min.getX())/2,
	    (max.getY() - min.getY())/2,
	    (max.getZ() - min.getZ())/2
	    );
	    
	    Vector3[] send = {min, middle, max};
	    
	    return send;
   	 
   }

And this is how I implement it:

in init

player.topSelection = getTopSelection(model);

in update

Vector3[] top = getPrimitive(model, player.topSelection);
        staff.setTranslation(model.getTranslation().getX() + (top[0].getX() + top[2].getX()), model.getTranslation().getY() -(top[0].getY() + top[2].getY()), model.getTranslation().getZ() +(top[0].getZ() + top[2].getZ()));
        staff.setRotation(model.getRotation());

It follows the model’s movements on the x axis, and the y axis, but when the primitive is moved down and left the spatial moves down and right, but if I reverse the x it shows up on the other side of the model. How can I fix this?

Why not using Spatial.getParent()?

int selection = 0;

You should rather use another value as it is confusing. If the top selection is not found or if it is found in the first iteration of the loop, this variable will contain 0.

Why not using the picking feature? Look at my source code… com.ardor3d.intersection.PickingUtil.findPick(…).

I’m trying to, for example make a person hold a sword. When the person’s hand moves the sword needs to move with the hand, not with the person. Using Spatial.getParent() would give me he entire model, and not the primitive that is it’s hand.
[/quote]

Good point. I’ll set it to -1.

Well, I find PickingUtil to be slow, so I stay away from it, lol.

It depends on the way you use it but if you have some information that allows at accelerate your computations, you’re right by not using it. PickingUtil on triangles can be very slow…

Alright, now I’m getting a error. (Note my game is still called TorusExample)


Throwable caught in MainThread - exiting
com.ardor3d.util.Ardor3dException: Transform is invalid
	at com.ardor3d.math.ValidatingTransform.validate(ValidatingTransform.java:26)
	at com.ardor3d.math.ValidatingTransform.setRotation(ValidatingTransform.java:52)
	at com.ardor3d.scenegraph.Spatial.setRotation(Spatial.java:553)
	at TorusExample.updateExample(TorusExample.java:627)
	at com.ardor3d.example.ExampleBase.update(ExampleBase.java:242)
	at com.ardor3d.framework.FrameHandler.updateFrame(FrameHandler.java:68)
	at com.ardor3d.example.ExampleBase.run(ExampleBase.java:145)
	at java.lang.Thread.run(Unknown Source)


On this line:


staff.setRotation(new Quaternion().fromAngleAxis(Math.toDegrees(a3), Vector3.UNIT_X).multiplyLocal(new Quaternion().fromAngleAxis(Math.toDegrees(b3), Vector3.UNIT_Y)).multiplyLocal(new Quaternion().fromAngleAxis(Math.toDegrees(y3), Vector3.UNIT_Z)));

So This is the formula I’m using:


Vector3[] top = getPrimitive(model, player.topSelection);

        double d3 = Math.sqrt(Math.pow(top[3].getX(), 2) + Math.pow(top[3].getY(), 2) + Math.pow(top[3].getZ(), 2));
        
        double a3 = Math.acos(top[3].getX()/d3);

        double b3 = Math.acos(top[3].getY()/d3);

        double y3 = Math.acos(top[3].getZ()/d3);

And this is my new get primitive.


public Vector3[] getPrimitive(Mesh m, int selection){
	   	m.updateWorldBound(true);
	   	 
		
	   	Vector3[] v3 = new Vector3[3]; 
	   	v3 = m.getMeshData().getPrimitive(selection, 0, v3); 
	   	
	   	Vector3 min = new Vector3((float)Math.min((float) Math.min(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
	    		(float)Math.min((float)Math.min(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
	    		(float)Math.min((float)Math.min(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    
		Vector3 max = new Vector3((float) Math.max((float)Math.max(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
			(float)Math.max((float)Math.max(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
			(float)Math.max((float)Math.max(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    
	    Vector3 middle = new Vector3(
	    (max.getX() - min.getX())/2,
	    (max.getY() - min.getY())/2,
	    (max.getZ() - min.getZ())/2
	    );
	    
	    Vector3 v = new Vector3();
	    v = max.subtract(min, v);
	    
	    v.normalizeLocal();
	    
	    Vector3[] send = {min, middle, max, v};
	    
	    return send;
   	 
   }

How do I fix this?

Alright, I think I fixed it, but it’s still moving down left when the primitive goes down right on translation.


Vector3[] top = getPrimitive(model, player.topSelection);

        double d3 = Math.sqrt(Math.pow(top[1].getX(), 2) + Math.pow(top[1].getY(), 2) + Math.pow(top[1].getZ(), 2));
        
        double a3 = Math.acos(top[1].getX()/d3);
        
        double b3 = Math.acos(top[1].getY()/d3);
        
        double y3 = Math.acos(top[1].getZ()/d3);

        
        staff.setRotation(new Quaternion().fromAngleAxis(a3, Vector3.UNIT_X).multiplyLocal(new Quaternion().fromAngleAxis(b3, Vector3.UNIT_Y)).multiplyLocal(new Quaternion().fromAngleAxis(y3, Vector3.UNIT_Z)).multiplyLocal(model.getRotation()));
    	staff.setTranslation(model.getTranslation().getX() + (top[0].getX() - top[1].getX()), model.getTranslation().getY() -(top[0].getY() + top[2].getY()), model.getTranslation().getZ() +(top[0].getZ() + top[1].getZ()));



public Vector3[] getPrimitive(Mesh m, int selection){
	   	m.updateWorldBound(true);
	   	 
		
	   	Vector3[] v3 = new Vector3[3]; 
	   	v3 = m.getMeshData().getPrimitive(selection, 0, v3); 
	   	
	   	Vector3 min = new Vector3((float)Math.min((float) Math.min(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
	    		(float)Math.min((float)Math.min(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
	    		(float)Math.min((float)Math.min(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    
		Vector3 max = new Vector3((float) Math.max((float)Math.max(v3[0].getXf(), v3[1].getXf()), v3[2].getXf()),
			(float)Math.max((float)Math.max(v3[0].getYf(), v3[1].getYf()), v3[2].getYf()),
			(float)Math.max((float)Math.max(v3[0].getZf(), v3[1].getZf()), v3[2].getZf()));
	    

	    Vector3 v2 = new Vector3();
	    v2 = max.add(min, v2);
	    v2.divideLocal(2);
	    v2.normalizeLocal();
	    
	    Vector3[] send = {min, v2, max};
	    
	    return send;
   	 
   }

If you need a faster solution to perform picking, use geometry shaders: