Three.js:通过轴上的点构建平面 [英] Three.js: Construct plane through points on axes

查看:35
本文介绍了Three.js:通过轴上的点构建平面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个平面,该平面通过(例如)x 轴上的 2 个、y 轴上的 3 个和 z 轴上的 12 个(换句话说,平面 6x + 4y + z =12).

I'm trying to create a plane that passes through (say) 2 on the x-axis, 3 on the y-axis and 12 on the z-axis (in other words, the plane 6x + 4y + z = 12).

到目前为止,我已经尝试使用点积创建一个水平面并围绕 3 个轴旋转它,这使我接近所需的平面,但它永远不会完全正确.

I've so far tried creating a horizontal plane and rotating it around the 3 axes using the dot product, which gave me close to the desired plane, but it would never be exactly right.

我怀疑我需要使用 Matrix4,但找不到合适的示例.

I suspect I need to use Matrix4, but couldn't find a suitable example.

推荐答案

这是构建它的一种方法,根据您的示例,您有三个向量,它们是规范基础的倍数 i,j,k例如

Here's one way to build it, from your example you have three vectors which are multiples of the canonical basis i,j,k e.g.

x = x_0 * [1 0 0]
y = y_0 * [0 1 0]
z = z_0 * [0 0 1]

平面由两件事定义:

  • 法线(垂直于平面的向量)
  • 原点到平面的距离

法线可以由位于平面上的任何两个非平行向量的叉积构建,例如y - xz - x 因此

The normal can be built from the cross product of any two non-parallel vectors that lie on the plane, e.g. y - x and z - x therefore

normal = normalize(cross(y - x, z - x))

现在当平面被渲染时,它会有一个初始法线N,我们可以创建一个四元数将向量N旋转到normal,我将使用轴角形式,其中

Now when the plane is rendered it will have an initial normal N, we can create a quaternion rotates the vector N to normal, I'll use the axis angle form where

q_{axis} = cross(N, normal)
q_{angle} = acos(dot(N, normal))

接下来可以用法线和平面上任意点的点积求出到平面的距离,例如

Next the distance to the plane can be found with the dot product of the normal and any point on the plane e.g.

distance = dot(normal, x)

请注意,这是一个带符号的值,非常棒,因为移动平面所要做的就是沿法线方向移动 distance 个单位

Note that this is a signed value which is awesome since all you have to do to move the plane is move it distance units in the normal direction

var plane = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  new new THREE.MeshNormalMaterial()
)
// ...
function rotatePlane(x, y, z) {
  var xy = new THREE.Vector3().subVectors(y, x)
  var xz = new THREE.Vector3().subVectors(z, x)
  var normal = new THREE.Vector3().crossVectors(xy, xz).normalize()

  // initial normal vector of the plane
  var Z = new THREE.Vector3(0, 0, 1)
  var axis = new THREE.Vector3().crossVectors(Z, normal).normalize()
  var angle = Math.acos(Z.dot(normal))
  var q = new THREE.Quaternion().setFromAxisAngle(axis, angle)
  plane.rotation.setFromQuaternion(q)

  var distanceToPlane = x.dot(normal)
  plane.position.copy(normal.clone().multiplyScalar(distanceToPlane))
}

演示

编辑 1:正如@WestLangley 所评论的,您可以使用 plane.quaternion.setFromUnitVectors( Z, normal ) ,它通过避免使用三角函数等来简化上述四元数,您可以在这篇很棒的文章

Demo

Edit 1: as @WestLangley commented you can use plane.quaternion.setFromUnitVectors( Z, normal ) which under the hood simplifies the quaternion described above by avoiding the use of trig functions among other things, you can read more about the simplification in this awesome article

编辑 2:@WestLangley 添加了关于法线方向的评论,这是完全有效的,在实现中,我决定渲染构成平面的三角形的两个面,而不是检查这个,如果你也想制作从不看原点的平面首先你从上面的等式中意识到,如果 distance 是负的,这意味着平面在看原点时远离原点,如果发生这种情况,你需要翻转normal 的方向也使得 distance 始终为正

Edit 2: @WestLangley added a comment about the direction of the normal which is completely valid, in the implementation instead of checking for this I decided to render both faces of the triangles that make the plane, if you also want to make the plane to never look at the origin first you realize from the above equations that if distance is negative that means that the plane moved away from the origin while looking at it, if this happens you need to flip the direction of the normal which also makes distance to always be positive

if (distance < 0) {
  distance *= -1
  normal.multiplyScalar(-1)
}

这篇关于Three.js:通过轴上的点构建平面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆