细分几何体的特定面。 Three.js

Subdivide a specific face of a geometry. Three.js

简单的问题,但我已经处理了很多。谁能想一想如何将一个 3 或 4 个顶点的面分成 2 个或更多更小的面?

您可能必须手动执行此操作,但对我来说似乎很有可能! 自从 2013 年移除四边形后,three.js 始终处理三角形,因此您必须考虑细分三角形。这就是它变得丑陋的地方,当你处理伪 4 顶点面时,因为它们是由两个三角形组成的。 通过一些矢量计算,你肯定可以解决问题,但需要做很多工作!

我已经为您编写了一个小演示。到目前为止还不完美,但我希望你能明白其中的原理 ;)

http://codepen.io/anon/pen/aOjgeL

HTML:

<html>
  <head>
    Subdivision
  </head>
  <body>
    <div class="button">Subdivide faces</div>
    <div id="rotateX">Rotate X</div>
    <div id="rotateY">Rotate Y</div>
    <div id="rotateZ">Rotate Z</div>
    <div id="container"></div>
  </body>
</html>

CSS:

#container {
    height: 400px;
    width: 800px;
    background-color: #feefee;
}
.button {
  background-color: BLACK;
  color: white;
  width: 150px;
  text-align: center;
}
#rotateX  {
  background-color: RED;
  color: white;
  width: 150px;
  text-align: center;
}
#rotateY  {
  background-color: GREEN;
  color: white;
  width: 150px;
  text-align: center;
}
#rotateZ  {
  background-color: BLUE;
  color: white;
  width: 150px;
  text-align: center;
}

Javascript:

var scene, camera, renderer, mesh;
var rotateX, rotateY, rotateZ;

$(document).ready(function(){
    init();
    animate();
});

function init(){
    // Create scene
    scene = new THREE.Scene();

    var container = document.getElementById("container");

    // Create WebGL renderer and add it to the DOM
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(800, 400);
    container.appendChild(renderer.domElement);

    // Create camera, zoom it out from the model and add it to the scene
    camera = new THREE.PerspectiveCamera(45, 800/400, 1, 10000);
    camera.position.set(6, 1, 2);

    // Set background color
    renderer.setClearColor(0xFFFFFF, scene);

    // Add light
    var light = new THREE.PointLight(0xFFFFFF);
    light.position.set(-1, 1, 1);
    scene.add(light);
    var light2 = new THREE.PointLight(0xFFFFFF);
    light2.position.set(1, 1, 1);
    scene.add(light2);
    var light3 = new THREE.PointLight(0xFFFFFF);
    light3.position.set(0, 0, 3);
    light3.intensity = 0.5;
    scene.add(light3);

    var geometry = new THREE.BoxGeometry( 1, 1, 1 );
    var material = new THREE.MeshPhongMaterial( {color: 0x000fff, side: THREE.DoubleSide} );
    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    camera.lookAt(mesh.position);

  var wireframe = new THREE.WireframeHelper(mesh, 0x00ff00);
  scene.add(wireframe);
}

$("#rotateX").click(function(){
  rotateX = (rotateX == true ? false : true);
});

$("#rotateY").click(function(){
  rotateY = (rotateY == true ? false : true);
});

$("#rotateZ").click(function(){
  rotateZ = (rotateZ == true ? false : true);
});

// This is where the magic happens
$(".button").click(function() {
  // Get the wanted face
  var face = mesh.geometry.faces[0];
  // Get the middle between two of the three vectors
  var vector = new THREE.Vector3( (mesh.geometry.vertices[face.b].x + mesh.geometry.vertices[face.c].x) / 2, (mesh.geometry.vertices[face.b].y + mesh.geometry.vertices[face.c].y) / 2, (mesh.geometry.vertices[face.b].z + mesh.geometry.vertices[face.c].z) / 2 );
  // Push vector in vertices array
  mesh.geometry.vertices.push(vector);
  var index = mesh.geometry.vertices.length - 1; // This method of getting the index is not thread safe!
  // Adding first face
  var temp = mesh.geometry.faces[0].b;
  mesh.geometry.faces[0] = new THREE.Face3(mesh.geometry.faces[0].a, index ,mesh.geometry.faces[0].c, mesh.geometry.faces[0].normal, mesh.geometry.faces[0].color, mesh.geometry.faces[0].materialIndex);
  // Adding second face
  mesh.geometry.faces.push( new THREE.Face3(temp, index, mesh.geometry.faces[0].c, mesh.geometry.faces[0].normal, mesh.geometry.faces[0].color, mesh.geometry.faces[0].materialIndex ) );

  mesh.geometry.verticesNeedUpdate = true;
  mesh.geometry.facesNeedUpdate = true;
});

function animate() {
  if(rotateY) mesh.rotateY(0.01);
  if(rotateZ) mesh.rotateZ(0.01);
  if(rotateX) mesh.rotateX(0.01);
  // Render the scene
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}