Quaternion.lookAt()

  • anyone have thoughts on this? ive tried multiple ways with different variables and always seem to get a rotation of 45-53 degrees. new to unit vectors so maybe im just doing something wrong!


  • I think I will repost here a simple solution that should help, it calculates quaternion from target position and original position:

    Java
    private Quaternion rotateTo(Vector3f objectPos, Vector3f lookPos) {
    Vector3f dir = lookPos.subtract(objectPos).normalizeLocal();
    float yaw = (float) Math.toDegrees(Math.atan2(dir.x, dir.z));
    float pitch = (float) Math.toDegrees(Vector3f.UP.dot(dir));
    return new Quaternion().fromAngles(pitch, yaw, 0);
    }

    Sometimes yaw can be inverted (depends on left/right axis rule used by game engine), in that case you can just swap x and z args. And if yaw has constant offset (for example 90 degrees) you can just add that value. Input of fromAngles method is in degrees. The last value in fromAngles is roll - rotation around direction axis

  • The Quaternion.lookAt() method requires a direction (as unit vector), not a target position (that wouldn't work anyway, because a quaternion just describes a rotation, so it has no "start position"). If you have two vectors (e.g. your player position a and a target position b), and you want to get a vector from a to b, you can calculate b - a. In order to turn the resulting vector into a unit vector (i.e. a vector with a length of 1), you have to normalize it ;)


    So the code could look like this:


  • morning^^


    I once found this post: https://stackoverflow.com/ques…uaternion-rotate-properly


    First I got the Vector3f direction from the dragon to the point by Utils.VectorUtils.getDirection

    Vector3f directionRot=Utils.VectorUtils.getDirection(dragon.getLocalPosition(),position.getPosition());

    Then I created a multiplier and determined which axes would be used, only Y

    Quaternion qFac = new Quaternion( 0, (float) Math.sin(PI/4), 0, (float) Math.cos(PI/4));

    Next I get the quaternion direction of the dragon

    Quaternion rRot = dragon.getLocalRotation().lookAt(directionRot);

    Then the multiplier is multiplied by the quaternion

    Quaternion fRot = qFac.multLocal(rRot);

    Now the new viewing direction can be added to the dragon by creating a new quaternion, cropping the axes here again to be on the safe side, and normalizing the whole thing

    dragon.setLocalRotation( new Quaternion(0, fRot.y, 0, fRot.w).normalizeLocal());


    This is just how I calculate the direction for myself.
    But I think if you adjust lines 12-18 and 21 it should work

  • There is basically no need for this additional math ^^ The lookAt method already does all required calculations under the hood, the only "math" part on your end is to calculate the direction, which is targetVector - startVector, then normalize it. But I forgot that we already have a Utils method for that, as pointed out by noci :saint: Of course you can use that one instead of calculating the direction manually (just bear in mind that the first parameter is the "start position", and the 2nd parameter is the "target position")


    This is a simplified version of my example above (using our utils method, but basically the utils method just performs the math posted above):

    Java
    //Get direction vector
    Vector3f direction = Utils.VectorUtils.getDirection(dragonposition, result.getCollisionPoint);
    //Get your new rotation looking at the direction
    Quaternion rotation = new Quaternion().lookAt(direction);
    //Let the dragon look at this position
    dragon.setLocalRotation(rotation);
  • Why this method is actually called lookAt (since there is a method with same name in Transform and it accepts target look point)? In quaternion there is a method called lookRotation, it is probably a better name for it since it clarifies that it doesn't look at position, but instead rotates to some specific direction

  • Why this method is actually called lookAt (since there is a method with same name in Transform and it accepts target look point)? In quaternion there is a method called lookRotation, it is probably a better name for it since it clarifies that it doesn't look at position, but instead rotates to some specific direction

    Basically we kept the method names from the Java version (to keep breaking changes as low as possible), and the old API was mostly using the naming convention of the engine (JMonkeyEngine), which also called it "lookAt" ^^


    But actually I wouldn't recommend to rely too much on Unitys API when it comes to Vectors or Quaternions, because Unity works quite different in this regard anyway. Java provides no way to overload operators (so Unity code like "Vector3 c = a - b;" wouldn't work in Java), and in addition to that, Java doesn't have structs like C# - so creating new vectors or quaternions always result in a new object on the heap, which may have performance implications - that's why there are various "local" methods in the vector and quaternion classes, e.g. "add" (which always creates a new vector) and "addLocal" (which updates the original vector) etc.


    The only API part which is directly related to Unity is Style (for UI elements). But apart from that, I wouldn't rely on Unitys API, because it is too different from the Plugin API.

  • Java doesn't have structs like C# - so creating new vectors or quaternions always result in a new object on the heap

    That's why Project Valhalla exists ;)
    Well, if most names are related to original Java API that's fine, this should help old users to switch to newer API

  • Ich stehe gerade auf dem Schlauch, vieleicht kann mir hier jemand helfen.

    I'm at a loss right now, maybe someone here can help me.



    Für die Situation der Blauen Rotation haben wir ja schon den weg gefunden.

    We have already found the way to deal with the blue rotation situation.






    Code
    //Get direction vector
    Vector3f direction = Utils.VectorUtils.getDirection(dragonposition, result.getCollisionPoint);
    //Get your new rotation looking at the direction
    Quaternion rotation = new Quaternion().lookAt(direction);
    //Let the dragon look at this position
    dragon.setLocalRotation(new Quaternion(0, rotation.y, 0, rotation.w));


    Ich versuche jetzt die Grüne Rotation hin zu bekommen, sie soll sich an der Normale vom Terang ausrichten.
    Allerdings finde ich da gerade kein Ansatz:dizzy:

    Ich habe die Normale(Blaue Zylinder) als Vector3f und die Rote Rotarion als Quaternion.
    Aktuell Dreht sich der Schräge Würfel um seine Ackse in der Roten Rotation, so das es eine von 360 blichrichtung gibt die Passt:hushed:

    I'm now trying to get the green rotation to align with the normal of the Terang.
    However, I can't find an approach at the moment:dizzy:

    I have the normal (blue cylinder) as Vector3f and the red rotarion as quaternion.
    Currently the slanted cube rotates around its axis in the red rotation, so that there is one of 360 light directions that fits:hushed:

    Code
    Quaternion qFac = new Quaternion(
        rayCast.getCollisionNormal().x*(float) Math.sin(PI/4f),
        rayCast.getCollisionNormal().y*(float) Math.sin(PI/2f),
        rayCast.getCollisionNormal().z*(float) Math.sin(PI/4f),
        (float) Math.cos(PI/4f)
    );
    Prefab.setLocalRotation( qFac.multLocal( new Quaternion(0, rotation.y, 0, rotation.w) ));
  • Sorry for my late response! :saint:


    I wouldn't necessarily recommend to work with individual quaternion values directly (i.e. the x, y, z and w values). There is really no need to understand the complex math voodoo behind them. If you just want to set rotation values directly (i.e. a rotation around the x, y and z axis), you can just use "euler angles" - the API has a fromAngles() method for that where you can set the pitch, yaw and roll.


    In your case it looks like you want to align something to the ground normal? This is a bit more complex, but you can just use vector math for that (which is much simpler and more comprehensible than quaternion math). Basically you just have to calculate a new direction vector (aligned to the ground normal) - this can be done by calculating the cross vector of the normal and forward, then use that to calculate the cross vector of the normal. The resulting vector can be used as direction for the Quaternion.lookAt() method (but it's necessary to provide an up vector then, which is just the normal in this case):


    We can add a new util method with the next update btw which can produce an "aligned direction" ;)

Participate now!

Don’t have an account yet? Create a new account now and be part of our community!