我该如何环绕3D球形文字 [英] How can i wrap a text arround 3D sphere

查看:130
本文介绍了我该如何环绕3D球形文字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在巴比伦或Threejs中将文本环绕在球体上的方法.而且我对改变javascript技术持开放态度

I'm looking for a way to wrap text around sphere in babylon or threejs. And i'm open-minded for changing javascript technology

推荐答案

我会看

I would look at an example of generating text. I’d then generate each letter separately recording their individual widths and use those to compute the total width across the string I want to display

然后我可以将每个网格作为 Object3D 的父对象,并将 Object3D 的旋转y设置为

I could then parent each mesh to an Object3D and set that Object3D’s rotation y to

widthSoFar = 0;
for each letter
   obj3d.rotation.y = widthSoFar / totalWidth * Math.PI * 2;
   widthSoFar += widthOfCurrentLetter;

然后将字母的position.z设置为一定的半径,以使字母围绕一个圆圈.

And set the letter’s position.z to some radius which would put the letters around a circle.

什么半径?

circumference = 2 * PI * radius

如此

radius = circumference / (2 * PI)

我们知道我们需要的周长,它是字符串的totalWidth.

We know the circumference we need, it’s the totalWidth of the string.

您可能会发现本教程有助于理解如何使用场景图节点(例如Object3D节点)来组织场景以满足您的需求.

You might find this tutorial helpful in understanding how to use scene graph nodes (like the Object3D node) to organize a scene to meet your needs.

'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 40;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 1000;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 70;

  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  function addLight(...pos) {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(...pos);
    scene.add(light);
  }
  addLight(-4, 4, 4);
  addLight(5, -4, 4);

  const lettersTilt = new THREE.Object3D();
  scene.add(lettersTilt);
  lettersTilt.rotation.set(
     THREE.Math.degToRad(-15),
     0,
     THREE.Math.degToRad(-15));
  const lettersBase = new THREE.Object3D();
  lettersTilt.add(lettersBase);
  {
    const letterMaterial = new THREE.MeshPhongMaterial({
      color: 'red',
    });  
    const loader = new THREE.FontLoader();
    loader.load('https://threejsfundamentals.org/threejs/resources/threejs/fonts/helvetiker_regular.typeface.json', (font) => {
      const spaceSize = 1.0;
      let totalWidth = 0;
      let maxHeight = 0;
      const letterGeometries = {
        ' ': { width: spaceSize, height: 0 }, // prepopulate space ' '
      };
      const size = new THREE.Vector3();
      const str = 'threejs fundamentals ';
      const letterInfos = str.split('').map((letter, ndx) => {
        if (!letterGeometries[letter]) {
          const geometry = new THREE.TextBufferGeometry(letter, {
            font: font,
            size: 3.0,
            height: .2,
            curveSegments: 12,
            bevelEnabled: true,
            bevelThickness: 0.5,
            bevelSize: .3,
            bevelSegments: 5,
          });
          geometry.computeBoundingBox();
          geometry.boundingBox.getSize(size);
          letterGeometries[letter] = {
            geometry,
            width: size.x / 2, // no idea why size.x is double size
            height: size.y,
          };
        }
        const {geometry, width, height} = letterGeometries[letter];
        const mesh = geometry
            ? new THREE.Mesh(geometry, letterMaterial)
            : null;
        totalWidth += width;
        maxHeight = Math.max(maxHeight, height);
        return {
          mesh,
          width,
        };
      });
      let t = 0;
      const radius = totalWidth / Math.PI;
      for (const {mesh, width} of letterInfos) {
        if (mesh) {
          const offset = new THREE.Object3D();
          lettersBase.add(offset);
          offset.add(mesh);
          offset.rotation.y = t / totalWidth * Math.PI * 2;
          mesh.position.z = radius;
          mesh.position.y = -maxHeight / 2;
        }
        t += width;
      }
      {
        const geo = new THREE.SphereBufferGeometry(radius - 1, 32, 24);
        const mat = new THREE.MeshPhongMaterial({
         color: 'cyan',
        });
        const mesh = new THREE.Mesh(geo, mat);
        scene.add(mesh);
      }
      camera.position.z = radius * 3;
    });
  }

  function resizeRendererToDisplaySize(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(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
    
    lettersBase.rotation.y = time * -0.5;

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();

body {
  margin: 0;
}
#c {
  width: 100vw;
  height: 100vh;
  display: block;
}

<canvas id="c"></canvas>
  <script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>

这篇关于我该如何环绕3D球形文字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆