Unity Rotation & Quaternions - rotation

I'm learning Unity and I have a question.
I dont understand why this line resets the rotation to 0,0,0. All I'm doing is re-assigning its euler values?
transform.rotation =
Quaternion.Euler(transform.rotation.x,
transform.rotation.y,
transform.rotation.z);
The reason I'm doing this is because I need to lock one axis and keep the others changing. So I thought I could do it like this after the changes in x and z axes occur:
transform.rotation = Quaternion.Euler(transform.rotation.x,
LOCKED ROTATION VALUE,
transform.rotation.z);
I'm sure its simple but I cant find out whats wrong.
Thanks in advance.

Here is some documentation with transform.Rotate(). I'd use this one for rotating.
// Here is an example if you want to just rotate the Z axis.
transform.Rotate(new Vector3(0, 0, 10f) * Time.deltaTime);
Also, here is some other documentation on Quaternion. You could use functions like RotateTowards.
If your game object has a rigidbody on it then you can lock the rotation of it in Unity. Click on the game object and under the Rigidbody component click Constraints and then click the axis under Freeze Rotation.

You are using transform.rotation as if it is exposing Euler angles (which it is not). If you want the Euler angles from your rotation, you have to do this:
transform.rotation =
Quaternion.Euler(transform.rotation.eulerAngles.x,
transform.rotation.eulerAngles.y,
transform.rotation.eulerAngles.z);

Related

Three.js rotating object around xyz world axis using quaternions

I've been struggling with this for the past 3 days so here we go:
I am building a virtual photo-studio using Three.js. The rotation is set with three sliders, one for each axis. Rotation needs to happen around the world axis. So far, I can get the object to rotate around the world x axis, however, y and z rotation only happens locally. Here is the code for one of the rotation sliders using quaternions.
let rotationX = new THREE.Quaternion()
sliderX.oninput = function () {
let newVec = new THREE.Vector3(1,0,0)
let newRad = THREE.Math.degToRad(this.value)
rotationX.setFromAxisAngle(newVec, newRad)
pivot.quaternion.multiplyQuaternions(rotationX, rotationY).multiply(rotationZ)
}
This approach has gotten me the farthest. The problem is that the rotation always happens around the vector of the first quaternion in the multiplication chain. That would be the quaternion "rotationX" of the following line.
pivot.quaternion.multiplyQuaternions(rotationX, rotationY).multiply(rotationZ)
Because I am working with quaternions, switching around the order of multiplication is also not an option as it changes the outcome.
Any help would be greatly appreciated.
Here is a link to the dependency free repo in case you want to recreate the situation: https://github.com/maxibenner/exporter

Gimbal lock at y axis 90 degrees

I found a problem with rotations.
Using the transform controls helper, if I rotate a mesh on the Y axis, when I reach 90 degrees everything is flipped by -180 degrees.
I think this is due to the software avoiding gimbal lock, how to avoid it?
That is, I would like the x- and z-angles to remain 0 degrees in the display.
I tried even on the threejs editor (https://threejs.org/editor/) and it occurs even there.
Please help me :)!
What you are describing is has nothing to do with Gimbal lock.
three.js is quaternion-based. An equivalent Euler angle representation is provided for convenience.
Euler angles are not unique; there are many Euler angles that represent the same orientation. See this answer for info on how Euler angles work in three.js.
If you want to rotate an object on the y-axis only, and have object.rotation.y be continuous, you can do so by changing the rotation order like so:
object.rotation.order = 'YXZ';
three.js r.87

How to Set Plane Mesh to always lookAt camera without tilting

I'm trying to make a Plane to always face the camera or another moving object but I want the Plane to only rotate on 1 axis. How can I use the lookAt function to make it only rotate side ways without tilting to look up or down at the moving object?
thanks, I managed to solve it easily by just keeping the y position of the rotating object constant.
if(planex){
var yaw_control = controls.getYawObject();
pos = new THREE.Vector3( yaw_control.position.x, planex.position.y, yaw_control.position.z );
planex.lookAt(pos);
}
http://www.lighthouse3d.com/opengl/billboarding/index.php?billCyl
maybe this article of any help for you. You are looking for those cylindrical billboards i think but read up from the first page ;) You can modify the specific mesh matrix yourself, although i am not sure if this is the most efficient way. I also did this myself once.
Get the camera look vec:
three.js set and read camera look vector
Then get the camera upVec and afterwards get the cross prodcut of those = rightVec according to the article above.
using those vectors, you can fill in a new Three.Matrix4() like explained in the article and then replace the meshes matrix with the newly created one. As I said, i am not quite into the matrix stuff in three.js but this works but it is probably not that efficient.
For this to work you will have to deactive the meshes auto matrix update with
mesh.matrixAutoUpdate = false;

Libgdx decal rotation around custom axis

I'm working app that uses Libgdx engine and decals in 3d space.
Now I need to rotate decals around X,Y,Z axis, but around custom pivot point that stands somewhere in the 3d space.
I found that decals have transformationOffset field, which might work with some calculations, but is Vector2 only. It means that I can move pivot point only over X and Y axis.
And when rotating decals over Y axis, wherever the pivot is, the result is the same.
decal.transformationOffset = new Vector2(0, -5);
decal.rotateX(newValues[0]);
decal.rotateY(newValues[1]);
decal.rotateZ(newValues[2]);
I need to move pivot over Z axis, too.
Is there some workaround for this issue?
Tnx!
EDIT:
I have succeded to rotate decal over pivot point in 3d space, but only if pivot's and decals's Z position is the same. If they are not I don't get what I've expected.
This is the code that works for pivot with same Z value:
decal.transformationOffset = new Vector2(pivotPosition.x - decal.getPosition().x, pivotPosition.y - decal.getPosition().y);
Tween.to(decal, DecalTween.XYZ_ROTATION, 5f).target(0, 360, 0).repeatYoyo(Tween.INFINITY, 0f).start(tweenManager);
And in tween I do this:
target.setRotationX(0);
target.setRotationY(0);
target.setRotationZ(0);
target.rotateX(newValues[0]);
target.rotateY(newValues[1]);
target.rotateZ(newValues[2]);
How to extend this to use and Z value for pivot. I'm trying to add and translation animation beside rotate to achive this, but the results is weird.
Tween.to(decal, DecalTween.MOVE_XYZ, 2.5f).target(decal.getPosition().x, decal.getPosition().y, pivotPosition.z - decal.getPosition().z).repeatYoyo(Tween.INFINITY, 0f).start(tweenManager);
decal.transformationOffset = new Vector2(pivotPosition.x - decal.getPosition().x, pivotPosition.y - decal.getPosition().y);
Tween.to(decal, DecalTween.XYZ_ROTATION, 5f).target(0, 360, 0).repeatYoyo(Tween.INFINITY, 0f).start(tweenManager);
Any idea how to combine translate and rotate animatio to get decal rotation in circle path over the pivot point?
I will answer my own question I guess.
I have extended Decal class, changed transformationOffset to Vector3.
Then in transformVertices I have added tz value, like there already was tx and ty. And add tz in calculation for vertex position.
Simple as that.
If anyone knows why is this left out from native libgdx support, please let me know.
Cheers.

How to rotate Decal over more then one axis at moment

I'm working on Libdx app using Decals.
Decals are 2d sprites in 3d world.
I have problem that when I say:
decal.setRotationX(angle)
everything works fine, but when I say:
decal.setRotationX(angle);
decal.setRotationY(angle2);
The decal rotates over Y axis only.
How to manage that problem?
I have found that Decal in source code uses Quaternion for rotation, but currently I don't know how to customize that to face my requirements.
Tnx in advance!
EDIT:
I have managed to rotate decal around multiple axis with:
decal.getRotation().setEulerAngles(yaw,pitch,roll);
Now my question is how to animate this with TweenEngine?
In get values method I have:
returnValues[0] = target.getRotation().getYaw();
returnValues[1] = target.getRotation().getPitch();
returnValues[2] = target.getRotation().getRoll();
In set values method I have:
target.getRotation().setEulerAngles(newValues[0], newValues[1],
newValues[2]);
But decal is not moving or animating, it's stucked in one position (slightly rotated over XYZ axis).
Any idea, values in TweenEngine are correct but somehow decal is not refreshing and rotating.
If you want to do it only once, you can do it like this:
decal.rotateX(angleX);
decal.rotateY(angleY);
decal.rotateZ(angleZ);
This will "add" the given angle to the current one though.
An alternative way would be to use the rotation Quaternion of the Decal:
decal.getRotation().setEulerAngles(yaw, pitch, roll);
The following image shows what "yaw", "pitch" and "roll" means:
Roll, pitch, yaw http://i.msdn.microsoft.com/dynimg/IC79189.gif
EDIT: I've just seen the JavaDoc of Decal.getRotation() and it says that the returned quaternion should not be modified! I've also checked the code and every other method of Decal sets an internal update flag which will cause the decal to change the next time it's rendered. Decal.getRotation() does not set this flag and thus the changes to it won't get recognized.
It seems like currently there is no really clean and easy way to set the rotation on all three axes at the same time. A workaround might look like this:
decal.setRotationX(0);
decal.setRotationY(0);
decal.setRotationZ(0);
decal.rotateX(angleX);
decal.rotateY(angleY);
decal.rotateZ(angleZ);
It first resets all angles to 0 and then rotates on each axis while not overwriting any other axis.

Resources