使用Three.js使用点创建桩的3D模型

时间:2018-11-15 13:23:40

标签: javascript three.js

我正在开发一个Web应用程序,该应用程序应该创建砾石桩的3D模型 用three.js用激光仪器测量的点。唯一的问题是 创建一个应该是包含所有点的桩面的船体。我已经用这些点制作了一个pointswarm模型,并尝试使用ConvexBufferGeometry在其周围制作一个船体,但是在使用ConvexBufferGeometry时,并非所有点都包含在船体中。有人可以指出正确的方向吗?

1 个答案:

答案 0 :(得分:1)

您可以尝试将Three.jsDelaunator库结合起来,对您的点进行三角剖分以制成曲面:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.setScalar(150);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
var canvas = renderer.domElement;
document.body.appendChild(canvas);

var controls = new THREE.OrbitControls(camera, canvas);

var light = new THREE.DirectionalLight(0xffffff, 1.5);
light.position.setScalar(100);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

var size = { x: 200, y: 200 };
var pointsCount = 1000;
var points3d = [];
for (let i = 0; i < pointsCount; i++) {
  let x = THREE.Math.randFloatSpread(size.x);
  let z = THREE.Math.randFloatSpread(size.y);
  let y = noise.perlin2(x / size.x * 5, z / size.y * 5) * 50;
  points3d.push(new THREE.Vector3(x, y, z));
}

var geom = new THREE.BufferGeometry().setFromPoints(points3d);
var cloud = new THREE.Points(
  geom,
  new THREE.PointsMaterial({ color: 0x99ccff, size: 2 })
);
scene.add(cloud);

// triangulate by [x, z]
var indexDelaunay = Delaunator.from(
  points3d.map(v => {
    return [v.x, v.z];
  })
);

var meshIndex = []; // delaunay index => three.js index
for (let i = 0; i < indexDelaunay.triangles.length; i++){
  meshIndex.push(indexDelaunay.triangles[i]);
}

geom.setIndex(meshIndex); // add three.js index to the existing geometry
geom.computeVertexNormals();
var mesh = new THREE.Mesh(
  geom, // re-use the existing geometry
  new THREE.MeshLambertMaterial({ color: "purple", wireframe: true })
);
scene.add(mesh);

var gui = new dat.GUI();
gui.add(mesh.material, "wireframe");

render();

function resize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}

function render() {
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  font-family: Verdana;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}

#info{
  position: absolute;
  margin-left: 10px;
}

a{
  color: yellow;
  text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<!-- https://github.com/mapbox/delaunator -->
<script src="https://unpkg.com/delaunator@3.0.2/delaunator.js"></script>

<script src="https://josephg.github.io/noisejs/perlin.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.min.js"></script>

<div id="info">
   <a href="https://github.com/mapbox/delaunator" target="blank">Delaunator<br>(triangulation)</a> 
</div>