THREE.JS | How to find out XYZ rotations between two vectors? - vector

THREE.js Noob here.
I have a mesh that I want to rotate by selecting on one of its faces. Basically, I want to click on a face, and apply rotations to the mesh so that the face I clicked on faces the plane that the mesh is currently sitting on.
Here is a visualization of my problem:
I want to click on a face (the yellow triangle) and rotate the mesh so that the yellow triangle faces the plane that the mesh is currently sitting on. I do have normal vector of the face (i.e., myVector) and I want to apply rotations so that the normal vector would equal targetVector after.
I would like to find out how much I would have to rotate the mesh in EACH axis separately in order to achieve my goal.
Thank you in advance and please ask me if you require any more information!

You'll need to use a THREE.Quaternion, apply the vectors, and then read the resulting rotations through a THREE.Euler:
// Set starting and ending vectors
var myVector = new THREE.Vector3(0.1, 1.0, 0.1);
var targetVector = new THREE.Vector3(0, 0, -1);
// Normalize vectors to make sure they have a length of 1
myVector.normalize();
targetVector.normalize();
// Create a quaternion, and apply starting, then ending vectors
var quaternion = new THREE.Quaternion();
quaternion.setFromUnitVectors(myVector, targetVector);
// Quaternion now has rotation data within it.
// We'll need to get it out with a THREE.Euler()
var euler = new THREE.Euler();
euler.setFromQuaternion(quaternion);
console.log(euler.toArray());
// Resulting euler will have x, y, z rotations in radians:
//[
// 0: -1.6704649792860586,
// 1: 0.09917726107940236,
// 2: 0.10956980436233299,
// 3: "XYZ"
//]

Related

How to access rotation data for mesh babylon.js

That was obtained by
BABYLON.SceneLoader.ImportMesh("",'', "ship.babylon", scene, function(newMeshes){
ship = newMeshes;
}
console.log(ship[0])
Question: How do I get the Y value Under rotationQuaternion
Hello simply call ship[0].rotationQuaternion
Just make sure there is a rotationQuaternion as rotation can also be expressed using Euler angles with .rotation which is a vector3

THREE.js: Why is my object flipping whilst travelling along a spline?

Following up from my original post Three.JS Object following a spline path - rotation / tangent issues & constant speed issue, I am still having the issue that the object flips at certain points along the path.
View this happening on this fiddle: http://jsfiddle.net/jayfield1979/T2t59/7/
function moveBox() {
if (counter <= 1) {
box.position.x = spline.getPointAt(counter).x;
box.position.y = spline.getPointAt(counter).y;
tangent = spline.getTangentAt(counter).normalize();
axis.cross(up, tangent).normalize();
var radians = Math.acos(up.dot(tangent));
box.quaternion.setFromAxisAngle(axis, radians);
counter += 0.005
} else {
counter = 0;
}
}
The above code is what moves my objects along the defined spline path (an oval in this instance). It was mentioned by #WestLangley that: "Warning: cross product is not well-defined if the two vectors are parallel.".
As you can see, from the shape of the path, I am going to encounter a number of parallel vectors. Is there anything I can do to prevent this flipping from happening?
To answer the why question in the title. The reason its happening is that at some points on the curve the vector up (1,0,0) and the tangent are parallel. This means their cross product is zero and the construction of the quaternion fails.
You could follow WestLangley suggestion. You really want the up direction to be the normal to the plane the track is in.
Quaternion rotation is tricky to understand the setFromAxisAngle function rotates around the axis by a given angle.
If the track lies in the X-Y plane then we will want to rotate around the Z-axis. To find the angle use Math.atan2 to find the angle of the tangent
var angle = Math.atan2(tangent.y,tangent.x);
putting this together set
var ZZ = new THREE.Vector3( 0, 0, 1 );
and
tangent = spline.getTangentAt(counter).normalize();
var angle = Math.atan2(tangent.y,tangent.x);
box.quaternion.setFromAxisAngle(ZZ, angle);
If the track leaves the X-Y plane things will get trickier.

How can I get view direction from the OpenGL ModelView Matrix?

I am writing a volume render program that constantly adjusts some plane geometry so it always faces the camera. The plane geometry rotates whenever the camera rotates in order to appear as if it doesn't move--relative to everything else in the scene. (I use the camera's viewing direction as a normal vector to these plane geometries.)
Currently I am manually storing a custom rotation vector ('rotations') and applying its affects as follows in the render function:
gl2.glRotated(rotations.y, 1.0, 0.0, 0.0);
gl2.glRotated(rotations.x, 0.0, 1.0, 0.0);
Then later on I get the viewing direction by rotating the initial view direction (0,0,-1) around the x and y axes with the values from rotation. This is done in the following manner. The final viewing direction is stored in 'view':
public Vec3f getViewingAngle(){
//first rotate the viewing POINT
//then find the vector from there to the center
Vec3f view=new Vec3f(0,0,-1);
float newZ=0;
float ratio=(float) (Math.PI/180);
float vA=(float) (-1f*rotations.y*(ratio));
float hA=(float) (-1f*rotations.x)*ratio;
//rotate about the x axis first
float newY=(float) (view.y*Math.cos(vA)-view.z*Math.sin(vA));
newZ=(float) (view.y*Math.sin(vA)+view.z*Math.cos(vA));
view=new Vec3f(view.x,newY,newZ);
//rotate about Y axis
float newX=(float) (view.z*Math.sin(hA)+view.x*Math.cos(hA));
newZ=(float) (view.z*Math.cos(hA)-view.x*Math.sin(hA));
view=new Vec3f(newX,view.y,newZ);
view=new Vec3f(view.x*-1f,view.y*-1f,view.z*-1f);
//return the finalized normal viewing direction
view=Vec3f.normalized(view);
return view;
}
Now I am moving this program to a larger project wherein the camera rotation is handled by a 3rd party graphics library. I have no rotations vector. Is there some way I can get my view direction vector from:
GLfloat matrix[16];
glGetFloatv (GL_MODELVIEW_MATRIX, matrix);
I am looking at this for reference http://3dengine.org/Modelview_matrix but I still don't get how to come up with the view direction. Can someone explain to me if it is possible and how it works?
You'll want to look at this picture # http://db-in.com/images/local_vectors.jpg
The Direction-of-Flight ( DOF) is the 3rd row.
GLfloat matrix[16];
glGetFloatv( GL_MODELVIEW_MATRIX, matrix );
float DOF[3];
DOF[0] = matrix[ 2 ]; // x
DOF[1] = matrix[ 6 ]; // y
DOF[2] = matrix[ 10 ]; // z
Reference:
http://blog.db-in.com/cameras-on-opengl-es-2-x/
Instead of trying to follow the modelview matrix, to adjust your volume rasterizer's fragment impostor, you should just adjust the modelview matrix to your needs. OpenGL is not a scene graph, it's a drawing system and you can, and should change things however they suit you best.
Of course if you must embedd the volume rasterization into a larger scene, it may be neccessary to extract certain info from the modelview matrix. The upper left 3×3 submatrix contains the composite rotation of models and view. The 3rd column contains the view rotated Z vector.

How do I take a 2D point, and project it into a 3D Vector by a perspective camera

I have a 2D Point (x,y) and I want to project it to a Vector, so that I can perform a ray-trace to check if the user clicked on a 3D Object, I have written all the other code, Except when I got back to my function to get the Vector from the xy cords of the mouse, I was not accounting for Field-Of-View, and I don't want to guess what the factor would be, as 'voodoo' fixes are not a good idea for a library. any math-magicians wanna help? :-).
Heres my current code, that needs FOV of the camera applied:
sf::Vector3<float> Camera::Get3DVector(int Posx, int Posy, sf::Vector2<int> ScreenSize){
//not using a "wide lens", and will maintain the aspect ratio of the viewport
int window_x = Posx - ScreenSize.x/2;
int window_y = (ScreenSize.y - Posy) - ScreenSize.y/2;
float Ray_x = float(window_x)/float(ScreenSize.x/2);
float Ray_y = float(window_y)/float(ScreenSize.y/2);
sf::Vector3<float> Vector(Ray_x,Ray_y, -_zNear);
// to global cords
return MultiplyByMatrix((Vector/LengthOfVector(Vector)), _XMatrix, _YMatrix, _ZMatrix);
}
You're not too fart off, one thing is to make sure your mouse is in -1 to 1 space (not 0 to 1)
Then you create 2 vectors:
Vector3 orig = Vector3(mouse.X,mouse.Y,0.0f);
Vector3 far = Vector3(mouse.X,mouse.Y,1.0f);
You also need to use the inverse of your perspective tranform (or viewprojection if you want world space)
Matrix ivp = Matrix::Invert(Projection)
Then you do:
Vector3 rayorigin = Vector3::TransformCoordinate(orig,ivp);
Vector3 rayfar = Vector3::TransformCoordinate(far,ivp);
If you want a ray, you also need direction, which is simply:
Vector3 raydir = Normalize(rayfar-rayorigin);

Method to combine multiple affine transforms as if each was specified in un-transformed space

I'm looking for a way to combine affine transforms in such a way so that the effect is equivalent to using each transform to manipulate a shape in succession. The problem is that if I simply concatenate the transforms, then each successive transform's effect is interpreted in the existing transform's co-ordinate space.
For example, consider a square around the origin (-50,-50, 100,100). I want to rotate it, and then translate it down 100px. If I take a transform and rotate and then translate, the translation gets interpreted in the rotated coordinates. Instead, if I transform the shape itself to rotate it, and then transform that shape again to translate it, both translations are interpreted in the "normal" un-translated plane, and it gives me what I want.
The problem is that for what I'm doing many transforms may take place, each of which needs to be interpreted in the normal coordinate plane, but I don't want to store a stack of transforms, nor can I simply keep manipulating a shape, because I need to at any time be able to create the final transformed shape from the original starting shape.
I'm aware that for this simple example if I did the translate before the rotate I'd get the same result, but that's missing the point. I'm dealing with an arbitrary set of successive scale, translate, and rotate transforms, so simply putting them in a certain order doesn't cut it.
I have an inkling that there should be a way to concatenate transforms in such a way that you modify the new transform before you concatenate it, correcting for the existing transform so that the effect is that the new transform appears to have been applied as if it were referencing the un-transformed coordinate plane. For example, if you translate by (70.7, 70.7) in the above example instead of (0,100), the result becomes equivalent. I just can't seem to figure out what the math is to figure out in general how to alter the new transform so it works out correctly.
Thanks for reading - hope this made sense. Heres the source of the example that created the screenshot:
public class TransformExample extends JPanel {
#Override
protected void paintComponent(Graphics _g) {
super.paintComponent(_g);
Graphics2D g = (Graphics2D) _g;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.translate(150, 100); // translate so we can see method 1 clearly
paintConcatenate(g);
g.translate(200, 0); // translate again so we can see method 2 to the right of method 1
paintSuccessive(g);
}
private void paintConcatenate(Graphics2D g) {
AffineTransform tx = new AffineTransform();
Shape shape = new Rectangle(-50, -50, 100, 100);
// Draw the 3 steps, altering the transform each time
draw(g, shape, tx, Color.GRAY);
tx.rotate(Math.PI / 4);
draw(g, shape, tx, Color.GREEN);
tx.translate(70.7, 70.7);
draw(g, shape, tx, Color.PINK);
}
private void paintSuccessive(Graphics2D g) {
Shape shape = new Rectangle(-50, -50, 100, 100);
// Draw the 3 steps, altering the shape each time with a new transform
draw(g, shape, null, Color.GRAY);
shape = AffineTransform.getRotateInstance(Math.PI / 4).createTransformedShape(shape);
draw(g, shape, null, Color.GREEN);
shape = AffineTransform.getTranslateInstance(0, 100).createTransformedShape(shape);
draw(g, shape, null, Color.PINK);
}
private void draw(Graphics2D g, Shape shape, AffineTransform tx, Color color) {
if (tx != null) {
shape = tx.createTransformedShape(shape);
}
g.setColor(color);
g.fill(shape);
}
public static void main(String[] args) {
JFrame f = new JFrame("Transform Example");
f.setSize(500, 350);
f.setContentPane(new TransformExample());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
(I'm working with Java2D, although I don't think the language or 2d library is all that pertinent here.)
I suggest you to keep track of some absolute values and then do less transformations as you can.
For example, store the translation matrix and the rotation angle around the origin.
int translate[2];
int rotate;
Now, suppose that you want to rotate around its center and then translate the object somewhere, and then rotate it again under its center.
Because with affine transformations, rotation matrix aren't commutative, so if you apply a rotation,translation, rotation you'll get an wrong result.
But you can simply sum the rotation angle of the first and third rotation, and apply a single rotation and then the translation.
Hope to be clear.
when you rotate an object, you normally rotate around a specific point. It looks like you are just rotating around (0,0) which is usually not what you want.
To rotate around a specific point (x,y),
translate the point to 0 (-x, -y),
then rotate,
then translate back (x, y).
public static AffineTransform getRotateInstance(double theta,
double anchorx,
double anchory)

Resources