0
votes

I have a program that rotates a cube based on some serial input. The serial input provides the absolute rotation the cube should be at (such as 20 degrees). I have limits on the cube's rotation such as X from -45 to 45 degrees.

I'm currently storing the current rotation for X,Y,Z, calculating the difference between the current rotation and the new rotation, and then using .rotateX() .rotateY() and .rotateZ() to rotate the cube based on its local position.

curX = 0; // Global variable

function updateCubeRotation(newX) {
    // Limit X
    if(newX < 45 && newX > -45) {
        cube.rotateX(THREE.Math.degToRad(newX - curX));
        curX = newX;
    }
}

This works great except in one scenario. When I first start my program if the serial data is outside of the soft limits, I can't easily set the cubes rotation to an absolute rotation such as 45 or -45. I could add in a check if the current rotation is not set and its outside of the limits, to set it to the limit value but this seems like a lot of unnecessary code.

I'm curious if there's a way to make SET (not add to) the absolute local rotation for an axis, instead of calculating the difference. This would also allow me to not have to keep track of the last local rotation value for each axis. Something like:

// Sets the cubes local rotation to 45, no matter what the current angle is 
cube.setRotateX(45); 

I'm guessing this is possible with quaterion calculations but I'm unsure of the math that needs to happen for this.

.quaternion : Quaternion
Object's local rotation as a Quaternion.

I was originally using cube.rotation.x = 45, but this rotates in the world space. Comparing this to Unity, they have the property cube.localRotation.x, which is what I'm trying to emulate.


Update

I see that the documentation says that .rotation is local but I'm still confused because from what I can tell its rotating via the world coordinates. Whats the difference between .rotateX and .rotation.x?

Logging both rotateX and rotation.x I can see that rotateX changes rotation.x, rotation.y and rotation.z to properly rotate on the local axis. Since more than 1 of the axis's has to change, than that means its relative to the world axis, which conflicts with the documentation?

Here are examples of rotateX and rotation.x:

rotateX - Desired rotation, but only takes the difference between last position and new position instead of an absolute value.

 console.log(cube.rotation.x)

 x       y       z
 0.1011 -0.6073 -0.5624
-0.0143 -0.5418 -0.6252
-0.1162 -0.4741 -0.6748
-0.2075 -0.4053 -0.7137
-0.2875 -0.3387 -0.7428
-0.3572 -0.2764 -0.7640
-0.4148 -0.2221 -0.7782
-0.4616 -0.1764 -0.7875
-0.4983 -0.1398 -0.7932
-0.5289 -0.1088 -0.7970

enter image description here

rotation.x - Undesired rotation

 console.log(cube.rotation.x)

 x       y       z
 0.6109 -0.0298 -0.7854
 0.6051 -0.0298 -0.7854
 0.4279 -0.0298 -0.7854
 0.2683 -0.0298 -0.7854
 0.1125 -0.0298 -0.7854
-0.0346 -0.0298 -0.7854
-0.1684 -0.0298 -0.7854
-0.3198 -0.0298 -0.7854
-0.5058 -0.0298 -0.7854
-0.6109 -0.0298 -0.7854

enter image description here


cube.rotation.x = THREE.Math.degToRad(45);

If .rotation was in fact local, wouldn't setting the x to degToRad(45) cause the rotation to be like the first example, but only need to change the x axis?


JS Fiddle Example

http://jsfiddle.net/jrj2211/m2cwvu0p/20/

1
I think you need to understand this: stackoverflow.com/questions/17517937/…WestLangley

1 Answers

1
votes

You can easily use the cube.rotation.x property to set an absolute value (instead of a change in value)

// Sets absolute rotation
setRotation(newRot) {
    // Clamps value so it does not exceed +/- 45
    var clampedRot = THREE.Math.clamp(newRot, -45, 45);

    // Assigns new rotation in radians
    cube.rotation.x = THREE.Math.degToRad(clampedRot);
}

I was originally using cube.rotation.x = 45, but this rotates in the world space.

I don't believe this is true. I think the problem is that if you use cube.rotation.x = 45, you'll get undesired results because rotation is calculated in radians, not degrees. Using literal 45 gives you about 7 full spins, you should be using THREE.Math.degToRad(45);