Three.js реализует динамический логотип Facebook Metaverse 3D

внешний интерфейс three.js
Three.js реализует динамический логотип Facebook Metaverse 3D

Это первый день моего участия в ноябрьском испытании обновлений, подробности о мероприятии:Вызов последнего обновления 2021 г.

задний план

FacebookНедавно переименовал свою материнскую компанию вMeta, объявили об официальном начале марша元宇宙 🪐поле. В этой статье в основном говорится оThree.js + Blenderстек технологий, реализацияMetaкомпания классная3DдинамичныйLogo, включая тор базовой модели, излом тора, создание конвейера и модели, загрузку модели, добавление анимации, добавление событий щелчка, изменение материалов и т. д.

что такое метавселенная

Метавселеннаятермин происходит от1992Нила Стефенсона《雪崩》, который описывает виртуальный мир, параллельный реальному мируMetaverse, у всех реальных людей есть кибераватарAvatar.维基百科Описание метавселенной:Благодаря виртуальной расширенной физической реальности присутствуют характеристики конвергенции и физического постоянства, основанные на будущем Интернете, с функциями восприятия связи и обмена.3DВиртуальное пространство.

метавселеннаяКоннотация состоит в том, чтобы поглотить информационную революцию5G/6G, интернет-революцияweb3.0, революция искусственного интеллекта иVR,AR,MR, особенно достижения технологической революции виртуальной реальности, включая игровые движки, демонстрирующие людям возможность построения голографического цифрового мира, параллельного традиционному физическому миру; запуская взаимодействие информатики, квантовой науки, математики и науки о жизни, меняя науку Парадигма, продвигает прорывы в традиционных философских, социологических и даже гуманитарных системах, охватывает все цифровые технологии. как фильм《头号玩家》место действия,Однажды в будущем люди смогут менять идентичность в любое время и в любом месте, свободно перемещаться между физическим миром и цифровым миром, жить и учиться в метавселенной, состоящей из узлов виртуального пространства и времени..

добиться эффекта

Переходя к теме, давайте взглянем на эффект реализации примера из этой статьи.

🔗онлайн просмотр:дракон IR.GitHub.IO/3-meta-log…(Из-за большого размера модели процесс загрузки может быть медленным, вам нужно терпеливо ждать)

Разработка и внедрение

📌Примечание: приведенный выше пример анимации показываетИспытание четыре, если вы не хотите видеть процесс проб и ошибок (проба 1, проба 2, проба 3), вы можете сразу перейти кИспытание четыреПункт, чтобы увидеть подробный процесс реализации. Трудности перечислены в процессе сбоя.Если вы знаете решение, пожалуйста, дайте мне несколько советов в области комментариев.

Прежде чем мы разработаем, давайте посмотримMeta Logo, можно обнаружить, что этоКольцо формируется путем складывания и скручивания пополам., поэтому вы можете начать с реализации тора при его реализации.

Испытание 1: THREE.TorusGeometry

Three.jsПредоставленная базовая геометрияTHREE.TorusGeometry(кольцо), это пончик, похожий на🍩простая графика. Основные параметры:

  • radius: необязательный. Определяет размер радиуса тора. Значение по умолчанию1.
  • tube: необязательный. Определяет радиус трубки тора. Значение по умолчанию0.4.
  • radialSegments: необязательный. Определяет количество сегментов по длине тора. Значение по умолчанию8.
  • tubularSegments: необязательный. Определяет количество сегментов в направлении ширины тора. Значение по умолчанию6.
  • arc: необязательный. Определяет, как долго рисуется тор. Диапазон значений0прибыть2 * π. Значение по умолчанию2 * π(полный круг).

Пример синтаксиса:

THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc);

😭 失败: Способа скрутить тор не найдено.

Испытание 2: THREE.TorusKnotGeometry

THREE.TorusKnotGeometryМожет использоваться для создания трехмерного излома тора, который представляет собой особый вид узла, который выглядит как трубка, вращающаяся вокруг себя несколько раз. Основные параметры:

  • radius: необязательный. Устанавливает радиус полного круга, значение по умолчанию1.
  • tube: необязательный. Устанавливает радиус трубы, значение по умолчанию0.4.
  • radialSegments: необязательный. Укажите количество сегментов сечения трубы. Чем больше сегментов, тем более сглажена окружность сечения трубы. Значение по умолчанию:8.
  • tubularSegments: необязательный. Укажите количество сегментов конвейера. Чем больше сегментов, тем плавнее конвейер. Значение по умолчанию:64.
  • p: необязательный. Определяет, сколько раз геометрия будет вращаться вокруг своей оси симметрии вращения, по умолчанию2.
  • q: необязательный. Определяет, сколько раз геометрия будет вращаться вокруг своего внутреннего тора, по умолчанию3.

Пример синтаксиса:

THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments , p, q);

😭 失败: Не найден способ управления степенью ручного искажения.

Испытание 3: THREE.TubeGeometry

THREE.TubeGeometryВыдавливает трубу по 3D-сплайну. Вы можете указать некоторую фиксированную точку для определения пути, а затем использоватьTHREE.TubeGeometryСоздайте эту трубку. Основные параметры:

  • path: это свойство используетTHREE.SplineCurve3объект, чтобы указать путь, по которому должен следовать конвейер.
  • segments: Этот атрибут указывает количество сегментов, используемых для построения этой трубы. По умолчанию64.Чем длиннее путь, тем больше сегментов нужно указывать.
  • radius: Это свойство определяет радиус трубы. По умолчанию1.
  • radiusSegments: Этот атрибут определяет количество сегментов окружности трубы. По умолчанию8, чем больше количество сегментов, тем более круглой выглядит труба.
  • closed: если свойство установлено вtrue, головка и хвост трубы будут соединены, значение по умолчанию равноfalse.

пример кода

// ...
var controls = new function () {
  // 点的位置坐标
  this.deafultpoints = [
    [0, 0.4, -0.4],
    [0.4, 0, 0],
    [0.4, 0.8, 0.4],
    [0, 0.4, 0.4],
    [-0.4, 0, 0],
    [-0.4, 0.8, -0.4],
    [0, 0.4, -0.4]
  ]
  this.segments = 64;
  this.radius = 1;
  this.radiusSegments = 8;
  this.closed = true;
  this.points = [];
  this.newPoints = function () {
    var points = [];
    for (var i = 0; i < controls.deafultpoints.length; i++) {
      var _x = controls.deafultpoints[i][0] * 22;
      var _y = controls.deafultpoints[i][1] * 22;
      var _z = controls.deafultpoints[i][2] * 22;
      points.push(new THREE.Vector3(_x, _y, _z));
    }
    controls.points = points;
    controls.redraw();
  };
  this.redraw = function () {
    redrawGeometryAndUpdateUI(gui, scene, controls, function() {
      return generatePoints(controls.points, controls.segments, controls.radius, controls.radiusSegments,
        controls.closed);
    });
  };
};
controls.newPoints();
function generatePoints(points, segments, radius, radiusSegments, closed) {
  if (spGroup) scene.remove(spGroup);
  spGroup = new THREE.Object3D();
  var material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: false });
  points.forEach(function (point) {
    var spGeom = new THREE.SphereGeometry(0.1);
    var spMesh = new THREE.Mesh(spGeom, material);
    spMesh.position.copy(point);
    spGroup.add(spMesh);
  });
  scene.add(spGroup);
  return new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), segments, radius, radiusSegments, closed);
}
// ...

😊 勉强成功: Однако кольцо, образованное трубами, недостаточно круглое, и для достижения идеальной дуги требуются точные координаты, а метод расчета координат пока не найден.

Пробная версия 4: Blender + Three.js

Хотя с помощьюTHREE.TubeGeometryЭтого можно добиться еле-еле, но эффект не очень хороший, для получения гладкого кольца нужно добавить к трубе точную функцию кривой скрученного тора. Из-за ограниченных математических способностей🤕️, я не нашел способа рассчитать искаженный путь дуги. Поэтому было решено решать ее с уровня моделирования.

成功 😄: Но я не умею пользоватьсяBlenderМоделирование занимает много времени💔.

Учебник по моделированию

посещениеB站Когда я нашел видео с сокровищами, опубликованное боссом, я просто решил свою проблему.

🎦Портал:[Учебник по динамическому дизайну] Как играть в блендер AE+? Динамический логотип Facebook Metaverse Meta был полностью проанализирован, изучен на 100%.

Моделирование с помощью Блендера

использоватьBlenderМоделируйте и экспортируйте анимациюfbxФормат, не забудьте проверить при экспорте烘焙动画опции.

зависимости нагрузки

<script src="./assets/libs/three.js"></script>
<script src="./assets/libs/loaders/FBXLoader.js"></script>
<script src="./assets/libs/inflate.min.js"></script>
<script src="./assets/libs/OrbitControls.js"></script>
<script src="./assets/libs/stats.js"></script>

инициализация сцены

var container, stats, controls, compose, camera, scene, renderer, light, clickableObjects = [], mixer, mixerArr = [], manMixer;
var clock = new THREE.Clock();
init();
animate();
function init() {
  container = document.createElement('div');
  document.body.appendChild(container);
  // 场景
  scene = new THREE.Scene();
  scene.transparent = true;
  scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000);
  // 透视相机:视场、长宽比、近面、远面
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(0, 4, 16);
  camera.lookAt(new THREE.Vector3(0, 0, 0));
  // 半球光源:创建室外效果更加自然的光源
  light = new THREE.HemisphereLight(0xefefef);
  light.position.set(0, 20, 0);
  scene.add(light);
  // 平行光
  light = new THREE.DirectionalLight(0x2d2d2d);
  light.position.set(0, 20, 10);
  light.castShadow = true;
  scene.add(light);
  // 环境光
  var ambientLight = new THREE.AmbientLight(0xffffff, .5);
  scene.add(ambientLight);
  // 网格
  var grid = new THREE.GridHelper(100, 100, 0xffffff, 0xffffff);
  grid.position.set(0, -10, 0);
  grid.material.opacity = 0.3;
  grid.material.transparent = true;
  scene.add(grid);
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 背景色设置为透明
  renderer.setClearAlpha(0);
  // 开启阴影
  renderer.shadowMap.enabled = true;
  container.appendChild(renderer.domElement);
  // 添加镜头控制器
  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 0, 0);
  controls.update();
  window.addEventListener('resize', onWindowResize, false);
  // 初始化性能插件
  stats = new Stats();
  container.appendChild(stats.dom);
}
// 屏幕缩放
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

📌Чтобы понять подробный процесс инициализации сцены, вы можете прочитать другую мою статью«Использование three.js для создания классных кислотных 3D-страниц».

Загрузить модель логотипа

использоватьFBXLoaderЗагрузите модель и установите положение и размер модели.

var loader = new THREE.FBXLoader();
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true;
    }
  });
  mesh.rotation.y = Math.PI / 2;
  mesh.position.set(0, 1, 0);
  mesh.scale.set(0.05, 0.05, 0.05);
  scene.add(mesh);
});

Добавить материал

эта статьяLogoиспользуетMeshPhysicalMaterialматериал, этоPBRФизические материалы, которые могут лучше имитировать расчеты освещения по сравнению с сетчатыми материалами с высоким освещением.MeshPhongMaterialЭффект рендеринга более реалистичен. использоватьTHREE.TextureLoaderдобавить в материалmapсвойство для загрузки текстуры модели. Изображение ниже представляет собой текстурную карту металлической текстуры.

var texLoader = new THREE.TextureLoader();
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      if (child.name === '贝塞尔圆') {
        child.material = new THREE.MeshPhysicalMaterial({
          map: texLoader.load("./assets/images/metal.png"),
          metalness: .2,
          roughness: 0.1,
          exposure: 0.4
        });
      }
    }
  });
})

Добавить анимацию

  • AnimationMixerОбъекты — это проигрыватели анимации для определенных объектов в сцене. Когда несколько объектов в сцене анимируются независимо, вы можете использовать по одному объекту для каждого объекта.AnimationMixer.
  • AnimationMixerобъектclipActionМетод создает экземпляр, который может управлять выполнением анимации.
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.animations.map(item => {
    mesh.traverse(child => {
      // 因为模型中有多个物体,并且各自有不同动画,示例中只为贝塞尔圆这个网格添加动画
      if (child.name === '贝塞尔圆') {
        let mixer = new THREE.AnimationMixer(child);
        mixerArr.push(mixer);
        let animationClip = item;
        animationClip.duration = 8;
        let clipAction = mixer.clipAction(animationClip).play();
        animationClip = clipAction.getClip();
      }
    })
  })
});

После добавления анимации не забудьтеrequestAnimationFrameОбновите анимацию в формате .

function animate() {
  renderer.render(scene, camera);
  // 获得前后两次执行该方法的时间间隔
  let time = clock.getDelta();
  // 更新logo动画
  mixerArr.map(mixer => {
    mixer && mixer.update(time);
  });
  // 更新人物动画
  manMixer && manMixer.update(time);
  stats.update();
  requestAnimationFrame(animate);
}

Показать ход загрузки

FBXLoaderВ то же время возвращаются две функции обратного вызова, которые можно использовать следующим образом для отображения отображения процесса загрузки модели и логической реализации сбоя загрузки.

<div class="loading" id="loading">
  <p class="text">加载进度<span id="progress">0%</span></p>
<div>
var loader = new THREE.FBXLoader();
loader.load('assets/models/meta.fbx', mesh => {
}, res => {
  // 加载进程
  let progress = (res.loaded / res.total * 100).toFixed(0);
  document.getElementById('progress').innerText = progress;
  if (progress === 100) {
    document.getElementById('loading').style.display = 'none';
  }
}, err => {
  // 加载失败
  console.log(err)
});

добиться эффекта

Нажмите, чтобы изменить материал

Слушайте событие клика на странице черезHREE.RaycasterПолучить текущий щелкнутый объект, чтобы показать пример, я изменил материал для щелкнутого объекта.THREE.MeshStandardMaterial, и назначьте ему случайноеcolorцвет,metalnessтекстура металла иroughnessшероховатость.

//声明raycaster和mouse变量
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseClick(event) {
  // 通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
  // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
  raycaster.setFromCamera(mouse, camera);
  // 获取raycaster直线和所有模型相交的数组集合
  let intersects = raycaster.intersectObjects(clickableObjects);
  if (intersects.length > 0) {
    console.log(intersects[0].object)
    let selectedObj = intersects[0].object;
    selectedObj.material = new THREE.MeshStandardMaterial({
      color: `#${Math.random().toString(16).slice(-6)}`,
      metalness: Math.random(),
      roughness: Math.random()
    })
  }
}
window.addEventListener('click', onMouseClick, false);

📌Для получения дополнительной информации о сетчатых материалах перейдите по ссылке в конце статьи.

Загрузить модель персонажа

Процесс загрузки модели персонажа иLogoПроцесс загрузки модели такой же. я добавил кастингЧерепаший цигунперсонажи, которые не ожидали быть связанными сLogoАнимация вращения модели хорошо вписывается😂.

loader.load('assets/models/man.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true;
    }
  });
  mesh.rotation.y = Math.PI / 2;
  mesh.position.set(-14, -8.4, -3);
  mesh.scale.set(0.085, 0.085, 0.085);
  scene.add(mesh);
  manMixer = new THREE.AnimationMixer(mesh);
  let animationClip = mesh.animations[0];
  let clipAction = manMixer.clipAction(animationClip).play();
  animationClip = clipAction.getClip();
}, res => {
  let progress = (res.loaded / res.total * 100).toFixed(0);
  document.getElementById('progress').innerText = progress + '%';
  if (Number(progress) === 100) {
    document.getElementById('loading').style.display = 'none';
  }
}, err => {
  console.log(err)
});

Пример модели персонажа в этой статье взят изmixamo.com, на сайте сотни персонажей и тысячи действий, которые можно свободно комбинировать,免费скачать. Вы можете выбрать своих любимых персонажей и анимационные действия для практикиThree.js.

Суммировать

Основные точки знаний, затронутые в этой статье, включают:

  • THREE.TorusGeometry: Звенеть.
  • THREE.TorusKnotGeometry: Тороидальный изгиб.
  • THREE.TubeGeometry:трубопровод.
  • Blender: моделирование.
  • FBXLoader: загрузить модель и отобразить ход загрузки.
  • TextureLoader: Загрузите материал.
  • THREE.AnimationMixer: загрузить анимацию.
  • THREE.Raycaster: фиксирует модель щелчка.

🔗Полный код:GitHub.com/дракон ИК/3…

использованная литература