Это первый день моего участия в ноябрьском испытании обновлений, подробности о мероприятии:Вызов последнего обновления 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站
Когда я нашел видео с сокровищами, опубликованное боссом, я просто решил свою проблему.
Моделирование с помощью Блендера
использовать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…