Rotating direction vectors

I have two 3d objects A and B which collide at a single point P (they could collide at several points at once, but I am only interested in a specific point at a time), this collision point P, hits a mesh triangle T1 on A and a mesh triangle T2 on B. I am trying to rotate B so that T1 and T2 are parallel, i.e. align their rotations so that T2 lies ‘flat’ on T1.

P is determined by two raycasts, one for each hit, which provides me with information of the meshes, collision point and triangles.

I am stuck rotating B with the correct amount.

I have tried calculating the normal vectors from the T1 and T2 (as they can simply be considered as planes in the world) and used Quaternion.FromToRotation/2 like this:

B.transform.rotation = Quaternion.FromToRotation(T2.normalVector,T1.normalVector);

Note that the code is slightly pseudo-like. This produces almost! the correct answer, although B is still rotating slightly wrong, taking the inverse of the result from FromToRotation, produces an even better result, but still not there.

Then I read somewhere that FromToRotation actually returns the amount of rotation that needs to be done before being hitting the target direction, but trying to work with this new information, just messes the rotation completely up!

I have also tried using many of the other Quaternion functions, even tried manually to calculate the axis and angle needed to rotate to the wanted direction (T1) and then use Quaternion.AngleAxis, although this doesn’t change the rotation at all.

I thought at first that this problem would be rather straight forward; I have two directions D1 and D2 and a object Obj, and I want to rotate Obj with the same rotation that it would take to align D1 with D2. But I am stuck! Endless of Quaternion tutorials, unityAnswer post and google searches later, and I am still stuck.

I appreciate any help or guidens, thanks in advance.

The following is the script that, at least tries to accomplish the above.
In the script A is referred to as primary and B is referred to as secondary.

#pragma strict

public var primary:GameObject;
public var secondary:GameObject;
private var attachmentHit : RaycastHit;

function Start () {

// - Find the hit of the initial attachmentment point on the secondary item
// Note this is the bottom 
	
// Get the position of the core of the secondary
var secCorePos : Vector3 = secondary.transform.Find("SecCore").gameObject.transform.position;

// Create the ray
var origin : Vector3 = secCorePos+Vector3.down;
var direction : Vector3 = secCorePos - origin;

// Cast the ray and fill the attachmentHit value
Physics.Raycast(origin, direction, attachmentHit, 100.0f, 1 << 9);
}

The following function is called when the secondary item is being dragged, it rotates and positions the secondary item based on the mouse position and primary item.

  function OnMouseDrag()
{
// - Calculate the next position and rotation of the secondary item

// Get the screen position of the mouse
var mpos : Vector2 = Input.mousePosition;
// Get the position of the core of the primary item
var primCorePos : Vector3 = primary.transform.Find("PrimCore").gameObject.transform.position;
// Translate the mouse screen position to a world position
var mposworld : Vector3 = GetWorldPosFromMousePoint(mpos,Vector3.Distance(primCorePos,
													Camera.main.transform.position));

// Create a ray from the mouse position to the primary core
var dis : float = Vector3.Distance(mposworld, primCorePos);
var dir : Vector3 = (primCorePos - mposworld).normalized;

// Cast the ray
var hits : RaycastHit[] = Physics.RaycastAll(mposworld, dir, dis, 1 << 8);
DebugUtils.Assert(hits.length > 0, "OnMouseDrag: There has to be atleast one hit!");

// Find the collision that was the furthest away from the core
// ie. shortest distance as the ray starts at mouse position
var outmosthit : RaycastHit = hits[0];
var prevdis : float = outmosthit.distance;
for (var i:int = 1; i < hits.length; i++)
{
	var nextdis : float = hits*.distance;*
  •   if (nextdis < prevdis)*
    
  •   {*
    

_ outmosthit = hits*;_
_
prevdis = nextdis;_
_
}_
_
}*_

// Returns self + all children (all levels)
var allChildren = secondary.GetComponentsInChildren(Transform);
for (var child : Component in allChildren) {
* // Move all children, including self*
* child.transform.position = outmosthit.point;*
}
* // Get the normal vector from the collision triangle on the primary object*
* var normalPrim : Vector3 = GetNormalVectorFromHit(outmosthit);*
* // Get the normal vector from the attachment triangle on the secondary object*
* var normalSec : Vector3 = GetNormalVectorFromHit(attachmentHit);*
* // Rotate the secondary object so its hit-triangle aligns with the hit-triangle of the primary object*
_ secondary.transform.rotation = Quaternion.FromToRotation(normalSec,-normalPrim) * secondary.transform.rotation;_
}
The following function (should) retrieve the normal vector from a triangle-hit
function GetNormalVectorFromHit(hit:RaycastHit) : Vector3
{
* // See link for details and this is partly taken from there*
_* // http://docs.unity3d.com/Documentation/ScriptReference/RaycastHit-barycentricCoordinate.html*_
* DebugUtils.Assert(hit != null, “GetNormalVectorFromHit: hit cannot be null”);*
* // Just in case, also make sure the collider also has a renderer*
* // material and texture*
* var meshCollider = hit.collider as MeshCollider;*
* DebugUtils.Assert(meshCollider != null, “GetNormalVectorFromHit: meshCollider cannot be null”);*
* DebugUtils.Assert(meshCollider.sharedMesh != null, “GetNormalVectorFromHit: sharedMesh cannot be null”);*

* var mesh : Mesh = meshCollider.sharedMesh;*
* var vertices = mesh.vertices;*
* var triangles = mesh.triangles;*
_ var p1 = vertices[triangles[hit.triangleIndex * 3 + 0]];
var p2 = vertices[triangles[hit.triangleIndex * 3 + 1]];
var p3 = vertices[triangles[hit.triangleIndex * 3 + 2]];_

* var u : Vector3 = p2 - p1;*
* var v : Vector3 = p3 - p1;*
* var normalVector : Vector3 = Vector3.Cross(u,v);*

* return normalVector.normalized;*
}
The following function converts a screen position to a world position
function GetWorldPosFromMousePoint(pos:Vector2,distance:float)
{
* var hit : RaycastHit;*
* var point : Vector3;*
* var ray : Ray = Camera.main.ScreenPointToRay(pos);*
* // http://answers.unity3d.com/questions/376735/get-world-coordinates-from-mouse-click.html*_
point = ray.origin + (ray.direction * distance); _

* return point;*
}

I believe what you are looking for is in terms of aligning the two normals is:

B.transform.rotation = Quaternion.FromToRotation(T2.normalVector,-T1.normalVector) * B.transform.rotation;

Note this will align the two rotations, but since the rotation is around the pivot point of ‘B’, this means that the points of contact may be pulled apart by the rotation. If you need code to bring them back into alignment, let me know.