【问题标题】:How can I cut a plane properly with 2D text shapes in three.js?如何在 three.js 中使用 2D 文本形状正确切割平面?
【发布时间】:2018-06-11 20:45:49
【问题描述】:

许多文本字符都有内部孔(如 a、b、d、e、g、o、p、q、0、4、6、8、9 等)。如果我采用它们的 2D 形状并使用它们在平面形状上切割孔,则只会切割这些形状的轮廓,并且每个字符的中心孔不会保留在平面形状上。

是否有使用文本形状正确切割平面的解决方案? 请注意,我正在寻找具有 2D 文本形状的原生 three.js 解决方案,而不是使用效率低得多的库和挤压 3D 文本。

示例主代码:二维文本形状切割矩形形状:

// text shapes
var message = "example";
var textshapes = font.generateShapes( message, 100, 2 );

// rectangle shape
var width = 800, height = 300, x = -130, y = -110;    
var rectShape = new THREE.Shape();
rectShape.moveTo( x, y );
rectShape.lineTo( x, y+height );
rectShape.lineTo( x+width, y+height );
rectShape.lineTo( x+width, y );
rectShape.lineTo( x, y );

//cut rectangle shape with the message's text shapes
var tslen = textshapes.length;
for (i=0; i<tslen; i++){
    rectShape.holes.push( textshapes[i] );
}

var geometry = new THREE.ShapeGeometry(rectShape);

结果:

【问题讨论】:

    标签: text three.js shape


    【解决方案1】:

    我最终采用了这种方法,使用.merge()。我不能说这是最好的解决方案(因为它是刚刚从头开始制作的),但至少它给出了一个可以接受的结果:

    var scene = new THREE.Scene();
    scene.background = new THREE.TextureLoader().load("https://threejs.org/examples/textures/UV_Grid_Sm.jpg");
    var clock = new THREE.Clock();
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
    camera.position.set(0, 0, 800);
    
    var renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0x101010);
    document.body.appendChild(renderer.domElement);
    
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
    
    var loader = new THREE.FontLoader();
    loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function(font) {
      // text shapes
      var message = "example8";
      var textshapes = font.generateShapes(message, 100, 2);
    
      // rectangle shape
      var width = 875,
        height = 300,
        x = -130,
        y = -110;
      var rectShape = new THREE.Shape();
      rectShape.moveTo(x, y);
      rectShape.lineTo(x, y + height);
      rectShape.lineTo(x + width, y + height);
      rectShape.lineTo(x + width, y);
      rectShape.lineTo(x, y);
    
      //cut rectangle shape with the message's text shapes
      var tslen = textshapes.length;
      for (i = 0; i < tslen; i++) {
        rectShape.holes.push(textshapes[i]);
      }
    
      var geometry = new THREE.ShapeGeometry(rectShape);
    
      for (let i = 0; i < tslen; i++) {
        let letter = textshapes[i];
        if (letter.holes && letter.holes.length > 0) {
          for (let j = 0; j < letter.holes.length; j++) {
            // here we make geometries from holes and merge them with the main geometry
            let hole = letter.holes[j];
            let pts = hole.getPoints();
    
            let innerShape = new THREE.Shape(pts);
            let innerGeom = new THREE.ShapeGeometry(innerShape);
            geometry.merge(innerGeom);
          }
        }
      }
    
      geometry.center();
    
      var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
        color: "aqua",
        side: THREE.DoubleSide
      }));
      scene.add(mesh);
    });
    
    function render() {
      requestAnimationFrame(render);
      renderer.render(scene, camera);
    }
    
    render();
    body {
      margin: 0;
      overflow: hidden;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/93/three.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

    Reference

    【讨论】:

    • 它可以工作,但它仍然是 2D 和原生的,所以它得到了我的投票。又快又好,干杯!
    【解决方案2】:

    stemkoski 的三个 csg 模块。不知道为什么要避免使用“库”,因为三个是非常模块化的,并且试图将您所描述的深奥功能保持在其核心之外。哼!

    【讨论】:

    • 你真的认为值得回答而不是评论吗?
    • 我不确定我是否理解您的问题?
    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    相关资源
    最近更新 更多