how can I calculate the rotation value of a model to look at a position?

I know that is there a look At method in the spatial class. but I need to have the exact value of rotation in the Y-axis to rotate the model animated and smoothly. not in one step and fast like sp.lookat().

# How can I calculate the rotation value of a model to look at a position?

**yn97**#1

**yaRnMcDonuts**#2

For smooth rotations, you could still use the `.lookAt()`

method to get the full rotation, and then you can use the slerp method to interpolate to that value each frame based on `tpf`

```
rotateQuat = new Quaternion();
rotateQuat.lookAt(lookAtPoint, upVar);
Quaternion currentQuat = model.getWorldRotation();
rotateQuat.slerp(currentQuat, 1 - (tpf * (rotateSpeed) ));
model.setLocalRotation(rotateQuat);
```

Something like this - although it may vary depending on whether your model is a direct child of the rootNode, or if it has one or more parent Nodes that have been rotated

**yn97**#3

why spatial.lookAt() method works correctly (it rotation is independent of any number of parents and their rotation) but I canâ€™t use it in this way?

```
public static float getLookAtPos(Node node, Vector3f position) {
Vector3f upVector = Vector3f.UNIT_Y;
float y = 0;
Vector3f worldTranslation = node.getWorldTranslation();
Vector3f compVecA = new Vector3f();
compVecA.set(position).subtractLocal(worldTranslation);
node.getLocalRotation().lookAt(compVecA, upVector);
if (node.getParent() != null) {
Quaternion rot = new Quaternion();
rot = rot.set(node.getParent().getWorldRotation()).inverseLocal().multLocal(node.getLocalRotation());
rot.normalizeLocal();
y = rot.toAngleAxis(upVector);
}
return y;
}
```

and use it like this:

head.rotate(0, getLookAtPos(head, new Vector3f(-34, 0, 1)), 0);

and the head is a Node with some child and body as parent and body is a child of the root Node. all of them may rotate in any axes. `rootNode->body->head`

.

I need to know how much rotate the head on the Y-axis to look at a position.

**pspeed**#4

You have a big misunderstanding about what an â€śangle axisâ€ť is. This code is actually corrupting the UNIT_Y vector because it will write its result to upVectorâ€¦ which youâ€™ve set to UNIT_Y.

If you want to know how far a spatial is rotated on the y axis then get the angles and grab the valueâ€¦ then deal with the 100 other problems you will have with this approach.

As recommended, itâ€™s better to stay with Quaternions. Figure out what your look QUATERNION needs to be then adjust that to the spatialâ€™s local space to interpolate.

To adjust a world rotation to spatial-local rotation, multiply it by the inverse of the parent rotation.

Quaternion localRot = spatial.getParent().getWorldRotation().inverse().mult(worldRot);

â€¦or something like that.

Even dealing with Euler angles as you are trying to do, you will have the same problem with world space versus local spaceâ€¦ as the local y axis is not going to be the same as the global y axis.

**sgold**#6

Welcome to the frustrating world of `com.jme3.math`

.

Hereâ€™s whatâ€™s in my Jme3utilities library:

```
/**
* Alter the world orientation of a spatial.
*
* @param spatial spatial to reorient (not null)
* @param worldOrientation desired world orientation (not null, unaffected)
* @throws IllegalArgumentException if the spatial is a geometry with
* ignoreTransform=true OR the parent's world orientation is not invertible
*/
public static void setWorldOrientation(Spatial spatial,
Quaternion worldOrientation) {
if (worldOrientation == null) {
throw new IllegalArgumentException("world orientation cannot be null");
}
if (isIgnoringTransforms(spatial)) {
throw new IllegalArgumentException("transform ignored");
}
Spatial parent = spatial.getParent();
if (parent == null) {
spatial.setLocalRotation(worldOrientation);
} else {
Quaternion rotation = inverseOrientation(parent);
rotation.multLocal(worldOrientation);
spatial.setLocalRotation(rotation);
}
}
/**
* Test whether a spatial is a geometry with ignoreTransform=true.
*
* @param spatial spatial to test (unaffected)
* @return true if the spatial ignores transforms, otherwise false
*/
public static boolean isIgnoringTransforms(Spatial spatial) {
boolean result = false;
if (spatial instanceof Geometry) {
Geometry geometry = (Geometry) spatial;
if (geometry.isIgnoreTransform()) {
result = true;
}
}
return result;
}
/**
* Construct the inverse of a spatial's world orientation, the quaternion
* that undoes all its rotations.
*
* @param spatial spatial to analyze (not null, unaffected)
* @return new instance
* @throws IllegalArgumentException if the spatial's world orientation is
* not invertible
*
*/
public static Quaternion inverseOrientation(Spatial spatial) {
Quaternion forward = spatial.getWorldRotation();
Quaternion result = forward.inverse();
if (result == null) {
throw new IllegalArgumentException("orientation not invertible");
}
return result;
}
```

To obtain the `worldOrientation`

, youâ€™d probably use `Quaternion.lookAt()`

but note that itâ€™s only useful if you want to point your local Z axis at something while keeping your local Y axis pointed upward. If you want to point some other axis, or use some other criterion to resolve ambiguity, `lookAt()`

wonâ€™t help you.

**yn97**#7

I want to look at a point and get the Y value of rotation, not rotate the spatial. is there any method to do that in Jme3Utilities library?

**sgold**#10

Do you define the angle relative to some world axis? Or is it relative to some local axis of the observer?

**pspeed**#11

Why do you want the Y value of rotation?

â€¦because your answer to that question will almost always lead back to us telling you that you donâ€™t need the value. It will be nothing but trouble.

**yn97**#14

I need the Y rotation to rotate the head of tank animated not fast in one step.

I need the Y value to use it in this way:

public void head_to(float deg) {

```
Quaternion qua = new Quaternion().fromAngleAxis(FastMath.DEG_TO_RAD * deg, new Vector3f(0, 1, 0));
Tween rot = SpatialTweens.rotate(head, head.getLocalRotation(), qua, 1f);
anim.add(Tweens.smoothStep(rot));
turning_sound.playInstance();
}
```

**pspeed**#16

Yes, and angle is not the best way to do thatâ€¦ then you need to deal with wrapping, errors in the angle extraction code, etcâ€¦ where you could pretty easily just â€śsteer left if itâ€™s leftâ€ť and â€śsteer right if itâ€™s rightâ€ť and thatâ€™s super-trivial dot-product based code. Available in any steering example.

**yn97**#17

because the target is not always at left or right it may be in any angle of 360 degree inâ€¦

**yaRnMcDonuts**#18

Referring back to my example, this line of code will do that for you, and then you do not need the y value at all

Notice how tpf is used to calculate the slerp value each frame, very similar to how you would multiply a movement vector by tpf and a constant speed value each frame to make it move smoothly.

**pspeed**#19

If you can only turn left or right to get thereâ€¦ then the target is either â€śturn to the leftâ€ť or â€śturn to the rightâ€ť.

How would you calculate that with a y angle?

With a couple of dot products itâ€™s simple.

Given: Spatial target, Spatial playerâ€¦ we want to figure out if player should turn left or right:

```
// Find the direction we want
Vector3f relativeDir = target.getWorldTranslation().subtract(player.getWorldTranslation()).normalizeLocal();
// Find the direction we're looking and the left vector
Vector3f fwdDir = player.getWorldTranslation().mult(Vector3f.UNIT_Z);
Vector3f leftDir = player.getWorldTranslation().mult(Vector3f.UNIT_X):
// Is it in front of us or behind us and how much?
float front = fwd.dot(relativeDir);
// Is it to the left or right and how much?
float left = leftDir.dot(relativeDir);
// left < 0, target is to the right, left > 0 target is to the left
// If it's behind us then just max out left or right
if( front < 0 ) {
left = FastMath.sign(left);
// Except if it's _exactly_ behind us the just pick left or right
if( left == 0 ) {
left = 1;
}
}
// Now turn left/right scaled by the left value -1 = max right turn, 1 = max left turn... 0.5 = half speed left turn, etc.
```

**sgold**#20

I believe what Paul and Ryan said is true: if you just want to aim the turret by turning it at a constant rate, you donâ€™t need the angle, just the sign (+/-) of the angle, which can be determined by a dot product. However, I can imagine valid reasons why you might want to know the magnitude of the angle as well:

- you might want the turret to accelerate and decelerate as it turns
- you might want AI to choose between multiple targets based on their angles
- you might use the turn angle to provide hints to the player (â€śtarget closing at 4 oâ€™clockâ€ť)

One simple approach to calculating the angle begins with transforming the targetâ€™s location into the turretâ€™s local coordinates. Let `targetInWorld`

be the targetâ€™s location in world coordinates and `turretToWorld`

be the `Transform`

that converts the turretâ€™s local coordinate to world coordinates. If you were using spatials as game objects (not recommended!) you might obtain these as follows:

```
Vector3f targetInWorld = target.getWorldTranslation(); // alias
Transform turretToWorld = turret.getWorldTransform(); // alias
```

The â€śaliasâ€ť comments are to remind you that these variables reference internal data structures that should not be modified directly.

The transformation to turret coordinates looks like this:

```
Vector3f targetInTurret = turretToWorld.transformInverseVector(targetInWorld, null);
```

And the turn angle (in radians, measured from the local +Z per your diagram) would be:

```
float turnAngleRadians = FastMath.atan2(x, z);
```

`atan2()`

returns a value in the range (-pi, pi). If you want a positive angle (0, 2 * pi), simply add 2*pi to any negative angle:

```
if (turnAngleRadians < 0f) {
turnAngleRadians += FastMath.TWO_PI;
}
```

To convert to radians to degrees, multiply by 180/pi:

```
float turnAngleDegrees = FastMath.RAD_TO_DEG * turnAngleRadians;
```

I hope that helps.