gpt4 book ai didi

three.js - 如何在 three.js 中绘制 3 空间中的平面形状?

转载 作者:行者123 更新时间:2023-12-05 03:06:36 26 4
gpt4 key购买 nike

我正在尝试在 three.js 中构建一组平面形状。每个都被定义为一系列共面的 Vector3 点,但形状并不都是共面的。将两个平面矩形想象成房子的屋顶,但形状要复杂得多。

我可以制作平面 Shape 对象,然后旋转和定位它们,但由于我的形状是在 3d 坐标中构思的,因此将其全部保存在 3 维空间中会简单得多,而 Shape 对象不喜欢这样。

有没有更直接的方法来简单地指定一组共面 Vector3,然后让 three.js 完成其余的工作?

最佳答案

我考虑了这个问题并提出了这个想法,当你有一组共面点并且你知道平面的法线(我们将其命名为 normal)时,你的点属于。

  1. 我们需要旋转点集使其平行于 xy 平面,因此该平面的法线为 [0, 0, 1](我们将其命名为 正常Z)。为此,我们使用 THREE.Quaternion().setFromUnitVectors() 找到四元数:

    var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);

  2. 四元数应用于我们的点集

  3. 因为它现在平行于 xy 平面,所以点的 z 坐标无关紧要,所以我们现在可以创建它们的 THREE.Shape() 对象。然后根据给定形状创建 THREE.ShapeGeometry()(将其命名为 shapeGeom),这将对我们的形状进行三角剖分。

  4. 我们需要将我们的点放回原来的位置,因此我们将对它们应用 quaternionBack

  5. 毕竟,我们会将点集分配给 shapeGeom.vertices 属性。

就是这样。如果它对你有用,请告诉我 ;)

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 20, 40);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(10, 0, 10);
controls.update();

var grid = new THREE.GridHelper(50, 50, 0x808080, 0x202020); // xy-grid
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);

var points = [ // all of them are on the xz-plane
new THREE.Vector3(5, 0, 5),
new THREE.Vector3(25, 0, 5),
new THREE.Vector3(25, 0, 15),
new THREE.Vector3(15, 0, 15),
new THREE.Vector3(15, 0, 25),
new THREE.Vector3(5, 0, 25),
new THREE.Vector3(5, 0, 5)
]

var geom = new THREE.BufferGeometry().setFromPoints(points);
var pointsObj = new THREE.Points(geom, new THREE.PointsMaterial({
color: "red"
}));
scene.add(pointsObj);

var line = new THREE.LineLoop(geom, new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(line);

// normals
var normal = new THREE.Vector3(0, 1, 0); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow

var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5, 0x00ffff)); // aqua

// 1 quaternions
var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);
var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);

// 2 make it parallel to xy-plane
points.forEach(p => {
p.applyQuaternion(quaternion)
});

// 3 create shape and shapeGeometry
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeGeometry(shape);

// 4 put our points back to their origins
points.forEach(p => {
p.applyQuaternion(quaternionBack)
});

// 5 assign points to .vertices
shapeGeom.vertices = points;

var shapeMesh = new THREE.Mesh(shapeGeom, new THREE.MeshBasicMaterial({
color: 0x404040
}));
scene.add(shapeMesh);

render();

function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.90.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.90.0/examples/js/controls/OrbitControls.js"></script>

关于three.js - 如何在 three.js 中绘制 3 空间中的平面形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49020699/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com