I’m a bit new to working with 3D space and rotation. I have a list of four Vector3 points that represent the corners of a rectangle. What I want to do is use those points to create a box mesh that is rotated to exactly match the angle of rotation of the points.
Here is a babylonjs playground demo showing what I mean. In it you can see I’ve drawn a simple line mesh between the points. That is great and the rectangle drawn is at the expected angle given the data. I’ve also created a box mesh and configured its dimensions to match and placed its center point in the proper center of the points. So far so good, however I cannot figure out how to rotate the box so that it’s top face is parallel with the face of the rectangle.
https://playground.babylonjs.com/#SN5K8L#2
var createScene = function () {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);
// This creates and positions a free camera (non-mesh)
var target = new BABYLON.Vector3(1.5, 4, 0)
var camera = new BABYLON.ArcRotateCamera("camera1", Math.PI / 2 + Math.PI, Math.PI / 4, 10, target, scene)
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
const axes = new BABYLON.AxesViewer(scene)
const points = [
new BABYLON.Vector3(1, 5, 1),
new BABYLON.Vector3(2, 5, 1),
new BABYLON.Vector3(2, 3, -1),
new BABYLON.Vector3(1, 3, -1)
]
const lines = BABYLON.MeshBuilder.CreateLines("lines", {
points: [...points, points[0]] // add a duplicate of first point to close polygon
}, scene)
const centerPoint = new BABYLON.Vector3(
(points[0].x + points[1].x + points[2].x + points[3].x) / 4,
(points[0].y + points[1].y + points[2].y + points[3].y) / 4,
(points[0].z + points[1].z + points[2].z + points[3].z) / 4
)
const width = Math.sqrt(
Math.pow(points[1].x - points[0].x, 2) +
Math.pow(points[1].y - points[0].y, 2) +
Math.pow(points[1].z - points[0].z, 2)
)
const depth = Math.sqrt(
Math.pow(points[2].x - points[1].x, 2) +
Math.pow(points[2].y - points[1].y, 2) +
Math.pow(points[2].z - points[1].z, 2)
)
const height = 0.15
const box = BABYLON.CreateBox("box", { width, height, depth}, scene)
box.position = centerPoint
//box.rotation = ???
return scene;
};
You can use Vector3.RotationFromAxis
to compute the required rotation in Euler angles:
const rotationAxisX = points[1].subtract(points[0])
const rotationAxisZ = points[1].subtract(points[2])
const rotationAxisY = rotationAxisZ.cross(rotationAxisX)
// RotationFromAxis has the side effect of normalising the input vectors
// so retrieve the box dimensions here
const width = rotationAxisX.length()
const depth = rotationAxisZ.length()
const height = 0.15
const rotationEuler = BABYLON.Vector3.RotationFromAxis(
rotationAxisX,
rotationAxisY,
rotationAxisZ
)
const box = BABYLON.CreateBox("box", { width, height, depth}, scene)
box.position = centerPoint
box.rotation = rotationEuler