ThreeJS 3D指向“平面”几何体(每个点连接到最近点)

时间:2017-12-29 15:49:56

标签: 3d three.js geometry

我正在使用THREE.ConvexGeometry绘制带有几个Vector3点的3d形状。这样它就会创建一个3d对象,但我实际上要创建的是一个“3d平面”。下面是代码生成内容的线框示例。我的目标是只获得一个简单的形状(红线)而不是整个体积。

enter image description here

代码是:

var material = new THREE.MeshPhongMaterial( {
    color: 0xff0000, 
    shading: THREE.FlatShading,
    wireframe: true
} );
material.side = THREE.DoubleSide;


let meshPoints = shapeData.meshPoints; //this is a variable
let points = [];
for (let i = 0; i < meshPoints.length; i++) {points.push(new THREE.Vector3(meshPoints[i][0],meshPoints[i][1],meshPoints[i][2]));        }
let geometry = new THREE.ConvexGeometry( points );

var mesh = new THREE.Mesh( geometry, material );
mesh.name = shapeData.name;

mesh.material.transparent = true;
mesh.material.opacity = 0.2;

window.scene.add( mesh );

2 个答案:

答案 0 :(得分:0)

当然,生成凸包的THREE.ConvexGeometry不是生成凹面的正确选择。

可能你想要THREE.PlaneGeometry

请参阅代码段:

(function onLoad() {
  var container, camera, scene, renderer, controls;
  
  init();
  animate();

  function createModel() {

    var radius0 = 60, radius1 = 20, height = 100,
        startAngle = THREE.Math.degToRad(-20),
        endAngle = THREE.Math.degToRad(110),
        horSegs = 25, vertSegs = 25;
    var width = radius0 * (endAngle-startAngle);
    var plane = new THREE.PlaneGeometry( width, height, horSegs, vertSegs);
    
    var index = 0;
    for (var i = 0; i <= vertSegs; i++) {
      for (var j = 0; j <= horSegs; j++) {
        var angle = startAngle + j / horSegs * (endAngle - startAngle);
        var vertRel = i / vertSegs;
        var r_add = Math.sin(vertRel*Math.PI);
        var radius = radius0 + radius1 * r_add;
        plane.vertices[index].z = radius * Math.cos(angle);
        plane.vertices[index].x = radius * Math.sin(angle);
        index++;
      }
    }
    plane.computeVertexNormals();

    var material = new THREE.MeshLambertMaterial({
      color: 0xa2cddd,
      side: THREE.DoubleSide
    });
    
    var mesh = new THREE.Object3D();
    var curve = new THREE.Mesh(plane, material);
    curve.rotation.z = THREE.Math.degToRad(-90);
    mesh.add(curve);
    mesh.position.x=0
    mesh.position.y=40
    mesh.position.z=-20
  
    scene.add(mesh);
  }

  function init() {
    container = document.getElementById('container');
    
    renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    container.appendChild(renderer.domElement);

    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);
    
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(-80, 40, -80);
    scene.add(camera);
    resize();
    window.onresize = resize;
    
    var ambientLight = new THREE.AmbientLight(0x404040);
    scene.add(ambientLight);

    var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
    directionalLight.position.x = -2;
    directionalLight.position.y = 2;
    directionalLight.position.z = -4;
    scene.add( directionalLight );

    controls = new THREE.OrbitControls(camera, renderer.domElement);
		
    addGridHelper();
    createModel();
  }

  function addGridHelper() {
    var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
    planeGeometry.rotateX(-Math.PI / 2);

    var planeMaterial = new THREE.ShadowMaterial({
      opacity: 0.2
    });
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.position.y = -200;
    plane.receiveShadow = true;
    scene.add(plane);

    var helper = new THREE.GridHelper(2000, 100);
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    scene.add(helper);

    var axis = new THREE.AxesHelper(1000);
    scene.add(axis);
  }

  function resize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    //controls.handleResize();
  }

  function animate() {
    requestAnimationFrame(animate);
    render();
  }

  function render() {
    renderer.render(scene, camera);
  }
})();
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<div id="container"></div>

答案 1 :(得分:0)

使用earcut Algorythm生成正确的三角形面。代码看起来像这样

let meshPoints = shapeData.meshPoints;
let geom = new THREE.Geometry();

// Triangulation
// generate array with earcut
let earcutArray = [];
for (var i = 0; i < meshPoints.length; i++) {
	earcutArray.push(meshPoints[i][0]);
	earcutArray.push(meshPoints[i][1]);
	earcutArray.push(meshPoints[i][2]);
}
let earcutFaces = earcut(earcutArray, null, 3);

//add vertices
for (var i = 0; i < meshPoints.length; i++) {
	geom.vertices.push(new THREE.Vector3(meshPoints[i][0],meshPoints[i][1],meshPoints[i][2]));
}

//add faces
let totalEarCutLength = earcutFaces.length;
for (var i = 0; i < totalEarCutLength/3; i++) {
	let one = earcutFaces[i*3];
	let two = earcutFaces[i*3+1];
	let three = earcutFaces[i*3+2];
	geom.faces.push( new THREE.Face3( one, two, three ) );
}

//add normals
geom.computeFaceNormals();

//material
let material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframe_linewidth: 25 } );
material.side = THREE.DoubleSide;

let mesh = new THREE.Mesh( geom, material );
window.scene.add( mesh );