Sense of an object

I have an object in my scene and I wanna move it always in sense of another object.

How I do it?

could you be a bit more specific?

Yes.



i have 2 objects.

The object 1 is moving, and the object 2 need to follow the object 1.

So I need to know in which direction to move the object 2 (Left,Right,Front,back)



Thanks

Hi, possibly this example will help you. Just test it.





[java]

import com.jme3.app.SimpleApplication;

import com.jme3.bounding.BoundingBox;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Ray;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;





public class move_node_on_surface extends SimpleApplication {



public static void main(String[] args) {

move_node_on_surface app = new move_node_on_surface();

app.start();

}



Node cubechar;

Node shootables;

Geometry mark;



Boolean shoot = false;

Vector3f vectry;

Vector3f vectry2;

Vector3f vecmove;

float vecdist2;



@Override

public void simpleInitApp() {

initCrossHairs(); // a "+" in the middle of the screen to help aiming

initKeys(); // load custom key mappings

initMark(); // a red sphere to mark the hit



/** create four colored boxes and a floor to shoot at: /

shootables = new Node("Shootables");

rootNode.attachChild(shootables);

shootables.attachChild(makeFloor());





cubechar = new Node();

cubechar.attachChild(makeCube("Character", 0, 0.5f, 0));

rootNode.attachChild(cubechar);

cubechar.setLocalTranslation(0,-3.8f,0);



flyCam.setMoveSpeed(30);

}



/
* Declaring the "Shoot" action and mapping to its triggers. /

public void initKeys() {

inputManager.addMapping("Shoot", new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar

new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click

inputManager.addListener(actionListener, "Shoot");

}

/
* Defining the "Shoot" action: Determine what was hit and how to respond. */

public ActionListener actionListener = new ActionListener() {



public void onAction(String name, boolean keyPressed, float tpf) {

if (name.equals("Shoot") && !keyPressed) {

// 1. Reset results list.

CollisionResults results = new CollisionResults();

// 2. Aim the ray from cam loc to cam direction.

Ray ray = new Ray(cam.getLocation(), cam.getDirection());

// 3. Collect intersections between Ray and Shootables in results list.

shootables.collideWith(ray, results);

// 4. Print the results

System.out.println("


Collisions? " + results.size() + "
");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}



if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
// rootNode.attachChild(mark);

shoot = true;






} else {
// No hits? Then remove the red mark.

// rootNode.detachChild(mark);
// shoot = false;

}

}


}



};

/** A cube object for target practice */
protected Geometry makeCube(String name, float x, float y, float z) {
Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);
Geometry cube = new Geometry(name, box);
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat1.setColor("m_Color", ColorRGBA.randomColor());
cube.setMaterial(mat1);
return cube;
}

/** A floor to show that the "shot" can go through several objects. */
protected Geometry makeFloor() {
Box box = new Box(new Vector3f(0, -4, -5), 15, .2f, 15);
Geometry floor = new Geometry("the Floor", box);
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat1.setColor("m_Color", ColorRGBA.Gray);
floor.setMaterial(mat1);
return floor;
}

/** A red ball that marks the last spot that was "hit" by the "shot". */
protected void initMark() {
Sphere sphere = new Sphere(30, 30, 0.2f);
mark = new Geometry("BOOM!", sphere);
Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mark_mat.setColor("m_Color", ColorRGBA.Red);
mark.setMaterial(mark_mat);
mark.setLocalTranslation(0, -3.8f, 0);
rootNode.attachChild(mark);
}

/** A centred plus sign to help the player aim. */
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // crosshairs
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}






@Override
public void simpleUpdate(float tpf)
{

float move = tpf*5.0f;
vectry = cubechar.getWorldTranslation();
vecmove = mark.getWorldTranslation();

float remainingDist = cubechar.getLocalTranslation().distance(vecmove);
if (remainingDist != 0){
vectry2 = vectry.interpolate(vecmove, move/remainingDist);

System.out.println(vectry);

// cubechar.setLocalTranslation(vectry2);
if (move < remainingDist) cubechar.setLocalTranslation(vectry2);
else cubechar.setLocalTranslation(vecmove);
}


}

}
[/java]

you can get the position of your Object1 (Vector 3f), then move your Object2 to the position of the Object1 and rotate your Object2 to that Vector.

To rotate… I think you need to interpolate (slerp) quaternion Object2 to Quaternion Object1.



Of course, if you have physics… so there will be different commands. But theory is the same. :slight_smile:

much easier

[java]

node.lookAt(posVector, upVector);

[/java]

as i think :slight_smile:

@oxplay2 , do you know how to rotate it slowly (with tpf)? LookAt is really cool, but I cannot understand how to rotate it slowly?

slowly is much harder. I just wroted my own function.

but for now i have better idea:

It must have:

  • start time of update
  • ending time of update.



    [java]vec1.angleBetween(vec2);[/java]



    we also can have angle(or 3 angles of x y and z) between two vectors so:



    when simpleUpdate calling.

    Then calculate how many it should rotate (using angles between two vectors).

    You understand what i mean?

    I think its best way imo.

Yeah… I think “slerp” willbe the angle between 2 quaternions.



I tried such a thing:



[java]

import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Quaternion;

import com.jme3.math.Transform;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;





public class rotate_node1 extends SimpleApplication {



public static void main(String[] args) {

rotate_node1 app = new rotate_node1();

app.start();

}







Vector3f vecmove = new Vector3f(25, 5, 0);

float angla;

Geometry geom;

Quaternion vectry;

Quaternion vectry2;

Vector3f vectry3;

float vecdist2;

Quaternion PITCH045;

Quaternion quat;

float xxx = FastMath.DEG_TO_RAD45f;



Quaternion qqq;



public void move (float tpf) {



float move = 0;

move += tpf
0.5f;



vectry = geom.getLocalRotation();

qqq = new Quaternion().fromAngleAxis(xxx, Vector3f.UNIT_Z);

float angle1 = vectry.toAngleAxis(new Vector3f(0, 0, 0));

float angle2 = qqq.toAngleAxis(new Vector3f(0, 0, 0));

float angle3 = (angle2 -angle1);





Transform transA = new Transform().setRotation(vectry);

Transform transB = new Transform().setRotation(qqq);

Transform transC = new Transform();







if (angla <= 3.14) {



angla += tpf * 0.5f;



geom.setLocalRotation(new Quaternion().fromAngles(0, angla, 0));



}









// else geom.setLocalTransform(transB);





System.out.println(angla);







}





@Override

public void simpleInitApp() {

Box b = new Box(Vector3f.ZERO, 1, 1, 1);

geom = new Geometry(“Box”, b);

geom.updateModelBound();



Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.setColor(“m_Color”, ColorRGBA.Blue);

geom.setMaterial(mat);



rootNode.attachChild(geom);







flyCam.setMoveSpeed(30);







}









@Override

public void simpleUpdate(float tpf)

{



move(tpf);





}



}

[/java]










And another one:
[java]
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;


public class rotate_node2 extends SimpleApplication {

public static void main(String[] args) {
rotate_node2 app = new rotate_node2();
app.start();
}



Vector3f vecmove = new Vector3f(25, 5, 0);
float angla;
Geometry geom;
Quaternion vectry;
Quaternion vectry2;
Vector3f vectry3;
float vecdist2;
Quaternion PITCH045;
Quaternion quat;


Quaternion qqq;

public void move (float tpf) {


float xxx = FastMath.DEG_TO_RAD*angla;
float move = 0;
move += tpf*1.5f;

vectry = geom.getLocalRotation();
vectry.normalize();
qqq = new Quaternion().fromAngleAxis(xxx, Vector3f.UNIT_Z);
qqq.normalize();
float angle1 = vectry.toAngleAxis(new Vector3f(0, 0, 0));
float angle2 = qqq.toAngleAxis(new Vector3f(0, 0, 0));
float angle3 = (angle2 -angle1);


Transform transA = new Transform().setRotation(vectry);
Transform transB = new Transform().setRotation(qqq);
Transform transC = new Transform();

//float angle3 = transA.d

if (angla <= 179.9f) {

angla += tpf * 10.5f;
transC.interpolateTransforms(transA, transB, angle3);
geom.setLocalTransform(transC);
}

//else geom.setLocalTransform(transB);


System.out.println(xxx);



}


@Override
public void simpleInitApp() {
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
geom = new Geometry("Box", b);
geom.updateModelBound();

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("m_Color", ColorRGBA.Blue);
geom.setMaterial(mat);

rootNode.attachChild(geom);



flyCam.setMoveSpeed(30);



}




@Override
public void simpleUpdate(float tpf)
{

move(tpf);


}

}


[/java]

WOW, this is fantastic!!!



[java]vec1.angleBetween(vec2);[/java]



Thanks!

i hope it was not ironic :wink: i always seek the easiest way to solution :slight_smile: and i cant tell which solution will be faster

Maybe im student of IT, but i hate hard matrix calculations

jme3.Math.Transform class is the best! It can calculate any action. move, rotate, scale… With matrix optimizations (not all matrices will be applied, as far as I know).

Just create an object:

[java]Transform tr = new Transform();[/java]



And you can do any things. :slight_smile:

yes i should think more about this :slight_smile: Tnx for advice

I’m at work and I dont’t have jMonkeyEngine here to test =S



but this code



[java]vec1.angleBetween(vec2);[/java]



If I rotate the object 2 with this angle returned, the object 2 look at object1? in the 3 axes?

i think yes, but if you want 1 axis you can just have.

[java]

Vector3f vec1axis1 = new Vector3f(x1,0,y1);

Vector3f vec2axis1 = new Vector3f(x2,0,y2);

[/java]

then it should give 1 axis…

great!



thanks

@oxplay2 , it’s interesting. I will test it.



What is updateLoop? Is it simpleUpdate()?

By the way, Transform is useful when you need to apply translation and rotation at one time.

Nice

I will try it

after I say if it worked

thanks