1
votes

I'm taking a given a rectangle (a face4) in space. The face4 can be at any angle/position in space.

I'm creating a torus at it's centroid.

I'm then trying to align my torus with the following criteria:

1) The plane bisects the torus horizontally (so that a half-circle appears on either side of the plane)

2) The torus is perpendicular to the plane

3) The torus is aligned to the midpoints of the two ("shorter") sides of the rectangular face, so that the torus is bisecting the "longer" sides of the rectangle/face4.

For example, it would look like this:

enter image description here

I feel like I'll need to do two different axis rotations for this. One to align it to the face, another to make it perpendicular.

Right now, I'm just attempting the first part (aligning it to the face4, not worrying about perpendicular), and I'm doing this:

1) Calculating two midpoints of the two sets of vectors from the face

2) Determining ending Torus axis by subtracting one midpoint from the other to get my axis.

3) Finding the rotation axis by doing a cross product of #2 and the (0,1,0) axis of the starting torus

4) Finding angle of rotation with a Math.cos( endAxis.dot (rotationAxis))

5) Rotating torus

6) Translating it

Unfortunately, it's not "aligning" the two points as I would hope see pictures).

I'm attempting different approaches (inversing the theta each time I try something new, etc.), but it's still not behaving as I expected. Is there something wrong with my approach or thinking?

The code I'm using is below. (I purposely kept it in long form with lots of comments to help with my thinking).

   this.createTorus = function (tubeMeshParams) {

    var torusRadius = 5;
    var torus = new THREE.TorusGeometry( torusRadius, 1.5, segments/10, 50 );
    fIndex = this.calculateFaceIndex();

    //Determine midpoint of line AB on Face
    var v1 = geometry.vertices[geometry.faces[fIndex].a];
    var v2 = geometry.vertices[geometry.faces[fIndex].b];
    var xMidAB = (v1.x + v2.x) / 2;
    var yMidAB = (v1.y + v2.y) / 2;
    var zMidAB = (v1.z + v2.z) / 2;
    var midpointAB = new THREE.Vector3( xMidAB, yMidAB, zMidAB);

    //Determine midpoint of line CD on Face
    var v3 = geometry.vertices[geometry.faces[fIndex].c];
    var v4 = geometry.vertices[geometry.faces[fIndex].d];
    var xMidCD = (v3.x + v4.x) / 2;
    var yMidCD = (v3.y + v4.y) / 2;
    var zMidCD = (v3.z + v4.z) / 2;
    var midpointCD = new THREE.Vector3( xMidCD, yMidCD, zMidCD);

    //Determine Ending Torus axis
    var endTorusAxis = new THREE.Vector3();
    endTorusAxis.subVectors( midpointCD, midpointAB );
    endTorusAxis.normalize();

    //Direction vector of Torus (Y = 1)
    var torusAxis = new THREE.Vector3( 0, 1, 0);

    //Find the axis of rotation through Cross Product
    var rotationAxis = new THREE.Vector3();
    rotationAxis.crossVectors( endTorusAxis, torusAxis );

     if ( rotationAxis.length() == 0)  // Acounting for special case where the axis are aligned
     {
         rotationAxis.set( 1, 0, 0);
     }
    rotationAxis.normalize();

    //Now that we have the needed data, determine angle of rotation
    var theta = Math.acos( endTorusAxis.dot( rotationAxis ));
    theta = -theta;

    //Don't use position, rotate, scale
    torus.matrixAutoUpdate = false;

    //Rotate it
    torus.applyMatrix(new THREE.Matrix4().makeRotationAxis( rotationAxis, theta));

    // Create mesh and scale
    torusLoop = new THREE.Mesh(torus, this.m);
    torusLoop.scale.x = torusLoop.scale.y = torusLoop.scale.z = tubeMeshParams['Scale'];

    //Determine Face centroid positions
    var cenPosX = geometry.faces[fIndex].centroid.x;
    var cenPosY = geometry.faces[fIndex].centroid.y;
    var cenPosZ = geometry.faces[fIndex].centroid.z;

    //Move the rotated torus around the centroid
    torusLoop.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(cenPosX, cenPosY, cenPosZ));
    torusLoop.geometry.computeCentroids();
    torusLoop.geometry.computeFaceNormals();
    torusLoop.geometry.computeVertexNormals();

    return torusLoop;
}
1

1 Answers

0
votes

Solved. I used the Matrix.lookAT() command which essentially creates rotation matrix based off of two orthogonal vectors (instead of just one non-orthogonal vector from makeRotationAxis). More specifically, it takes three inputs: eye, center, and up, and generates the orthogonal vectors from those.

Details can be found here:

http://threejs.org/docs/58/#Reference/Math/Matrix4function