Three.js 如何制作全斜角立方体?

Three.js how to make a FULLY beveled cube?

我正在尝试制作一个斜角立方体,但我似乎不知道如何制作。我找到了 THREE.ExtrudeGeometry here,但如果您注意到,在示例编辑器中它只有顶面和底面有斜边,所以我得到的是这样的:

而不是像这样的东西,这就是我想要的:

代码:

        var bevelShape = new THREE.Shape();
        bevelShape.moveTo(0, unitSize - 0.2);
        bevelShape.lineTo(0, unitSize - 0.2);
        bevelShape.lineTo(unitSize - 0.2, unitSize - 0.2);
        bevelShape.lineTo(unitSize - 0.2, 0);
        bevelShape.lineTo(0, 0);

        var extrudeSettings = {
            steps: 20,
            depth: unitSize - 0.2,
            bevelEnabled: true,
            bevelThickness: 0.1,
            bevelSize: 0.1,
            bevelOffset: 0,
            bevelSegments: 1
        };

        var blockGeometry = new THREE.ExtrudeGeometry(bevelShape, extrudeSettings);
        var blockMaterial = new THREE.MeshStandardMaterial({color: color, roughness: 1, metalness: -1});
        var block = new THREE.Mesh(blockGeometry, blockMaterial);
        scene.add(block);

我应该怎么做才能做到这一点?

谢谢!

您可以构建自己的几何图形。

或者随意搜索论坛,因为您可以在那里找到许多有用且有趣的东西。

例如:https://discourse.threejs.org/t/faceted-box-geometry/5474

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(15, 10, 20).setLength(130);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0x404040);
//renderer.setPixelRatio(0.5);
var canvas = renderer.domElement;
document.body.appendChild(canvas);

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

var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.set(1, 2, 1);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

for (let i = 0; i < 11; i++) {
  let r = 10;
  let posX = (-5 + i) * 12.5;
  let wireGeom = facetedBox(r, r, r, i * 0.5, true);
  let wire = new THREE.LineSegments(
    wireGeom,
    new THREE.LineBasicMaterial({ color: Math.random() * 0x808080 + 0x808080 })
  );
  wire.position.x = posX;
  scene.add(wire);

  let geom = facetedBox(r, r, r, i * 0.5, false);
  let mesh = new THREE.Mesh(
    geom,
    new THREE.MeshStandardMaterial({
      color: Math.random() * 0x808080 + 0x808080,
      flatShading: true
    })
  );
  mesh.position.x = posX;
  scene.add(mesh);
}

var clock = new THREE.Clock();

renderer.setAnimationLoop(() => {
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

  renderer.render(scene, camera);
});

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;
}
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
  function facetedBox(w, h, d, f, isWireframed){
    let hw = w * 0.5, hh = h * 0.5, hd = d * 0.5;
    let vertices = [
      // px
      hw, hh - f, -hd + f,   // 0
      hw, -hh + f, -hd + f,  // 1
      hw, -hh + f, hd - f,   // 2
      hw, hh - f, hd - f,    // 3
      
      // pz
      hw - f, hh - f, hd,    // 4
      hw - f, -hh + f, hd,   // 5
      -hw + f, -hh + f, hd,  // 6
      -hw + f, hh - f, hd,   // 7
      
      // nx
      -hw, hh - f, hd - f,   // 8
      -hw, -hh + f, hd - f,  // 9
      -hw, -hh + f, -hd + f, // 10
      -hw, hh - f, -hd + f,  // 11
      
      // nz
      -hw + f, hh - f, -hd,  // 12
      -hw + f, -hh + f, -hd, // 13
      hw - f, -hh + f, -hd,  // 14
      hw - f, hh - f, -hd,   // 15
      
      // py
      hw - f, hh, -hd + f,   // 16
      hw - f, hh, hd - f,    // 17
      -hw + f, hh, hd - f,   // 18
      -hw + f, hh, -hd + f,  // 19
      
      // ny
      hw - f, -hh, -hd + f,  // 20
      hw - f, -hh, hd - f,   // 21
      -hw + f, -hh, hd - f,  // 22
      -hw + f, -hh, -hd + f  // 23
    ];
    
    let indices = [
      0, 2, 1, 3, 2, 0,
      4, 6, 5, 7, 6, 4,
      8, 10, 9, 11, 10, 8,
      12, 14, 13, 15, 14, 12,
      16, 18, 17, 19, 18, 16,
      20, 21, 22, 23, 20, 22,
      
      // link the sides
      3, 5, 2, 4, 5, 3,
      7, 9, 6, 8, 9, 7,
      11, 13, 10, 12, 13, 11,
      15, 1, 14, 0, 1, 15,
      
      // link the lids
      // top
      16, 3, 0, 17, 3, 16,
      17, 7, 4, 18, 7, 17,
      18, 11, 8, 19, 11, 18,
      19, 15, 12, 16, 15, 19,
      // bottom
      1, 21, 20, 2, 21, 1,
      5, 22, 21, 6, 22, 5,
      9, 23, 22, 10, 23, 9,
      13, 20, 23, 14, 20, 13,
      
      // corners
      // top
      3, 17, 4,
      7, 18, 8,
      11, 19, 12,
      15, 16, 0,
      // bottom
      2, 5, 21,
      6, 9, 22,
      10, 13, 23,
      14, 1, 20
    ];
    
    let indicesWire = [
      0, 1, 1, 2, 2, 3, 3, 0,
      4, 5, 5, 6, 6, 7, 7, 4,
      8, 9, 9, 10, 10, 11, 11, 8,
      12, 13, 13, 14, 14, 15, 15, 12,
      16, 17, 17, 18, 18, 19, 19, 16,
      20, 21, 21, 22, 22, 23, 23, 20,
      // link the sides
      2, 5, 3, 4,     //px - pz
      6, 9, 7, 8,     // pz - nx
      10, 13, 11, 12, // nx - nz
      15, 0, 14, 1,   // nz - px
      
      // link the lids
      // top
      16, 0, 17, 3,   // px
      17, 4, 18, 7,   // pz
      18, 8, 19, 11,  // nx
      19, 12, 16, 15,  // nz
      // bottom
      20, 1, 21, 2,
      21, 5, 22, 6,
      22, 9, 23, 10,
      23, 13, 20, 14
    ];
    
    let geom = new THREE.BufferGeometry();
    geom.setAttribute("position", new THREE.BufferAttribute(new Float32Array(vertices), 3));
    geom.setIndex(isWireframed ? indicesWire : indices);
    if (!isWireframed) geom.computeVertexNormals();
    return geom;
  }
</script>