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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在three.js的3空间中绘制扁平形状?相关的知识,希望对你有一定的参考价值。

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

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

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

答案

我想到了这个问题并提出了这个想法,当你有一组共面点并且你知道飞机的正常情况(让我们把它命名为qazxsw poi),你的点属于它。

1)我们需要旋转我们的点集使其平行于xy平面,因此该平面的法线是normal(让我们将它命名为[0, 0, 1])。为此,我们找到normalZ.setFromUnitVectors()的四元数:

THREE.Quaternion()

2)将var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ); var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal); 应用于我们的一组点

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

4)我们需要将我们的观点恢复到原来的位置,所以我们将shapeGeom应用于他们。

5)毕竟,我们将把我们的一组点分配给quaternionBack.vertices属性。

而已。如果它对您有用,请告诉我;)

shapeGeom
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;
}

以上是关于如何在three.js的3空间中绘制扁平形状?的主要内容,如果未能解决你的问题,请参考以下文章

如何在three.js中生成具有3个面的形状

Three.js/webgl RayCasting Sprites 在具有透明度或替代方案的场景中

Three.js - 3D 空间中的 2D 对象(通过 Vertices)

《Three.js 入门指南》3.1.1 - 基本几何形状 -圆形(CircleGeometry)

一篇文章教你在三维空间中创建流动线条(three.js实战1)

绘制不断变色的台体,BufferGeometry和ShaderMaterial的黄金组合(three.js实战5)