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.
much easier
[java]
node.lookAt(posVector, upVector);
[/java]
as i think
@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 += tpf0.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 i always seek the easiest way to solution 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.
yes i should think more about this 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
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