在three.js中从3个顶点渲染平面



我正在尝试将一个平面渲染为一组3个顶点(如图所示(。然而,我尝试的每一种方法(主要来自SO或官方的three.js论坛(都不适合我

// example vertices
const vert1 = new THREE.Vector3(768, -512, 40)
const vert2 = new THREE.Vector3(768, -496, 40)
const vert3 = new THREE.Vector3(616, -496, 40)

我已经尝试了下面的代码来计算平面的宽度和高度,但我认为这太复杂了(因为我只计算X和Y坐标,如果我把Z坐标和平面的位置也加到这个逻辑中,我认为我的代码会呈指数增长(。

const width = vert1.x !== vert2.x ? Math.abs(vert1.x - vert2.x) : Math.abs(vert1.x - vert3.x)
const height = vert1.y !== vert2.y ? Math.abs(vert1.y - vert2.y) : Math.abs(vert1.y - vert3.y)

示例:我想创建一个有a、B和C点三个角的平面,以及一个有D、E和F点三个点的平面。

示例视频

您可以使用THREE.Plane.setFromCoplanarPoints((从三个共面点创建一个平面。然而,THREE.Plane的实例只是将3D空间划分为两半空间的无限平面的数学表示。如果你想可视化它,可以考虑使用THRE.PlaneHelper。或者你可以使用下面线程中的方法从THREE.Plane的实例中派生一个平面网格。

Three.js-来自Math.Plane 的PlaneGeometry

我创建了计算三角形最长边中点的算法。在此之后,计算从不在最长边上的点到中点的向量。最后,只需将计算出的矢量加到中点,就可以得到第四点的坐标。

最后,只需从这些点创建PlaneGeometry并创建网格。代码是打字稿。此处编码:

type Line = {
startPoint: Vector3;
startPointIdx: number;
endPoint: Vector3;
endPointIdx: number;
vector: Vector3;
length: Vector3;
}
function createTestPlaneWithTexture(): void {
const pointsIn = [new Vector3(28, 3, 3), new Vector3(20, 15, 20), new Vector3(1, 13, 3)]
const lines = Array<Line>();
for (let i = 0; i < pointsIn.length; i++) {
let length, distVect;
if (i <= pointsIn.length - 2) {
distVect = new Vector3().subVectors(pointsIn[i], pointsIn[i + 1]);
length = distVect.length()
lines.push({ vector: distVect, startPoint: pointsIn[i], startPointIdx: i, endPoint: pointsIn[i + 1], endPointIdx: i + 1, length: length })
} else {
const distVect = new Vector3().subVectors(pointsIn[i], pointsIn[0]);
length = distVect.length()
lines.push({ vector: distVect, startPoint: pointsIn[i], startPointIdx: i, endPoint: pointsIn[0], endPointIdx: 0, length: length })
}
}
// find longest edge of triangle
let maxLine: LineType;
lines.forEach(line => {
if (maxLine) {
if (line.length > maxLine.length)
maxLine = line;
} else {
maxLine = line;
}
})
//get midpoint of longest edge
const midPoint = maxLine.endPoint.clone().add(maxLine.vector.clone().multiplyScalar(0.5));
//get idx unused point
const idx = [0, 1, 2].filter(value => value !== maxLine.endPointIdx && value !== maxLine.startPointIdx)[0];
//diagonal point one
const thirdPoint = pointsIn[idx];
const vec = new Vector3().subVectors(midPoint, thirdPoint);
//diagonal point two diagonal === longer diagonal of reactangle
const fourthPoint = midPoint.clone().add(vec);
const edge1 = thirdPoint.clone().sub(maxLine.endPoint).length();
const edge2 = fourthPoint.clone().sub(maxLine.endPoint).length();
//const topLeft = new Vector3(bottomLeft.x, topRight.y, bottomLeft.y);
const points = [thirdPoint, maxLine.startPoint, maxLine.endPoint, fourthPoint];
// console.log(points)
const geo = new PlaneGeometry().setFromPoints(points)
const texture = new TextureLoader().load(textureImage);
texture.wrapS = RepeatWrapping;
texture.wrapT = RepeatWrapping;
texture.repeat.set(edge2, edge1);
const mat = new MeshBasicMaterial({ color: 0xFFFFFFF, side: DoubleSide, map: texture });
const plane = new Mesh(geo, mat);
}

最新更新