首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在three.js中在3空间内绘制平面形状?

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

Stack Overflow用户
提问于 2018-02-28 01:40:09
回答 1查看 3.4K关注 0票数 3

我试图在three.js中构建一个平面形状的集合。每个点都定义为一系列共面Vector3点,但形状并不都是共面的。想象一个房子的屋顶有两个扁平的长方形,但形状复杂得多。

我可以制作平面形状的物体,然后旋转并定位它们,但是由于我的形状是在三维坐标下构思的,所以将其保持在3空间中要简单得多,而形状对象并不喜欢。

是否有更直接的方法来简单地指定一个共面向量数组,并让three.js来完成剩下的工作?

EN

Stack Overflow用户

回答已采纳

发布于 2018-03-01 13:30:31

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

  1. 我们需要旋转我们的点集,使其与xy平面平行,因此该平面的法线是[0, 0, 1] (让我们将其命名为normalZ)。为此,我们使用.setFromUnitVectors() of THREE.Quaternion()找到了四元数: 变量四元数=新的THREE.Quaternion().setFromUnitVectors(normalZ,().setFromUnitVectors(normal,normalZ);
  2. quaternion应用于我们的点集
  3. 因为它现在与xy平面平行,所以点的z坐标并不重要,所以我们现在可以为它们创建一个THREE.Shape()对象。然后从给定的形状创建THREE.ShapeGeometry() (命名为shapeGeom),这将对我们的形状进行三角化。
  4. 我们需要把我们的观点回到他们原来的立场,所以我们将quaternionBack应用于他们。
  5. 毕竟,我们将把我们的一组点分配给.verticesshapeGeom属性。

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

代码语言:javascript
运行
复制
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);
}
代码语言:javascript
运行
复制
body {
  overflow: hidden;
  margin: 0;
}
代码语言:javascript
运行
复制
<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>

票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49020699

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档