dot - скалярное произведение wiki, Khan Academy
Where
-
$| \vec{a} |, | \vec{b} |$ - magnitudes/lengths -
$\theta$ - is the angle between$\vec{a}$ and$\vec{b}$
Результат dot
для 2 нормализированных векторов, отображает их сонаправленность:
- 1 - повернуты в одну сторону;
- 0 - перпендикулярны;
- -1 - повернуты в разные стороны.
function dot( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z;
}
cross - векторное произведение wiki
Результат cross
для 2 нормализированных векторов, третий вектор перпендикулярный первому и второму.
function crossVectors( a, b ) {
const ax = a.x, ay = a.y, az = a.z;
const bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
}
vector.applyMatrix4 matrixWorld.multiplyMatrices
function worldToLocal( vector ) {
return vector.applyMatrix4( this.matrixWorld.clone().invert() );
}
function localToWorld( vector ) {
return vector.applyMatrix4( this.matrixWorld );
}
function updateMatrixWorld( force ) {
if ( this.parent === null ) {
this.matrixWorld.copy( this.matrix );
} else {
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
}
}
let parentInverseMatrix = parentNode.matrixWorld.clone().invert();
let localMatrix = parentInverseMatrix.clone().multiply(childNode.matrixWorld);
localMatrix.decompose(childNode.position, childNode.quaternion, childNode.scale);
childNode.updateMatrixWorld();
X-pitch, Y-yaw, Z-roll
// Rotate object during touch
const cameraPosition = new Vector3();
const object = Object3D();
const objectWorldPosition = object.getWorldPosition(new Vector3());
const objectWorldQuaternion = object.getWorldQuaternion(new Quaternion());
// Touch down
const pointStart = new Vector3();
const axis = 'X';
const objectQuaternionStart = object.quaternion.clone();
// Touch move
const pointEnd = new Vector3();
const offset = new Vector3().copy(pointEnd).sub(pointStart);
const ROTATION_SPEED = 10 / objectWorldPosition.distanceTo(cameraPosition);
const unit = {
X: new Vector3(1, 0, 0),
Y: new Vector3(0, 1, 0),
Z: new Vector3(0, 0, 1)
};
const rotationAxis = unit[axis].clone();
const rotationAxisWorld = rotationAxis.clone().applyQuaternion(objectWorldQuaternion);
const rotationAngle = offset.dot(rotationAxisWorld.cross(this.eye).normalize()) * ROTATION_SPEED;
const quaternion = new Quaternion().setFromAxisAngle(rotationAxis, rotationAngle);
object.quaternion.copy(objectQuaternionStart);
object.quaternion.multiply(quaternion).normalize();
A(m x s) * B(s x n) = C(m x n)
[1] [1*2 1*4 1*1] [2 4 1]
[4] * [2 4 1] = [4*2 4*4 4*1] = [8 16 4]
[3] [3*2 3*4 3*1] [6 12 3]
[1]
[2 4 1] * [4] = [2*1 + 4*4 + 1*3] = [21]
[3]
[3 4]
[1 2] * [5 6] = [1*3+2*5 1*4+2*6] = [13 16]
[2 -3 1] [-7 5] [2*(-7)+(-3)*2+1*4 2*5+(-3)*(-1)+1*3] [-16 16]
[5 4 -2] * [2 -1] = [5*(-7)+4*2+(-2)*4 5*5+4*(-1)+(-2*3)] = [-35 15]
[4 3]
if let projection = cameraPOV.camera?.projectionTransform {
let pointInClipSpace = simd_float4(
Float(touchPoint.x / viewSize.width) * 2 - 1.0,
1.0 - Float(touchPoint.y / viewSize.height) * 2,
0.5,
1
)
let projectionInverse = simd_inverse(simd_float4x4(projection))
let pointInCameraSpace = simd_mul(projectionInverse, pointInClipSpace)
var pointInWorldSpace = simd_mul(cameraPOV.simdWorldTransform, pointInCameraSpace)
pointInWorldSpace = pointInWorldSpace / pointInWorldSpace.w // Homogeneous divide
let rayOrigin = cameraPOV.simdWorldPosition
let touchPointWorld = simd_float3(pointInWorldSpace.x, pointInWorldSpace.y, pointInWorldSpace.z)
let rayDirection = simd_normalize(touchPointWorld - rayOrigin)
let rayQuery = ARRaycastQuery(origin: rayOrigin, direction: rayDirection, allowing: .estimatedPlane, alignment: .any)
let result = sceneView.session.raycast(rayQuery)
}
simd_float4x4([
[0.9635658, -0.1529741, 0.2194079, 0.0],
[0.12268591, 0.9816985, 0.14565793, 0.0],
[-0.23767428, -0.11343274, 0.9646989, 0.0],
[0.8025118, 0.47077584, 0.4210831, 1.0]])
)
// where position: (0.8025118, 0.47077584, 0.4210831)