Как вращать тор в 3js изнутри наружу?

Вопрос или проблема

Представьте себе это вращение как вращение прямой трубки вокруг её самой длинной оси, затем я изгибаю её в форму тора, и вращение продолжается.
Я пробовал с трубкой и с тором, но не могу достичь такого вращения.

Здесь вы можете увидеть, что я попробовал до сих пор, первая трубка, как она должна вращаться, и вторая, которую я пытался сформировать в тор, но это не закончилось хорошо.
Демо CodePen

<canvas id="bg"></canvas>
  <script  type="importmap">{
    "imports": {
        "three": "https://threejs.org/build/three.module.js",
        "three/addons/": "https://threejs.org/examples/jsm/"
    }
}</script>

canvas {
    position: fixed;
    left: 0;
    top: 0;
}

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.setZ(10);
camera.position.setX(10);
camera.position.setY(10);

const renderer = new THREE.WebGLRenderer({
    canvas: document.querySelector('#bg')
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

const pointLightWhite = new THREE.PointLight(0xffffff, 100);
pointLightWhite.position.set(0,10,0);
pointLightWhite.decay = 1;
scene.add(pointLightWhite);

const lightHelper = new THREE.PointLightHelper(pointLightWhite);
scene.add(lightHelper);

const ambientLight = new THREE.AmbientLight(0xffffff, 4 * Math.PI);
scene.add(ambientLight);

const axesHelper = new THREE.AxesHelper(20);
scene.add(axesHelper);

const gridHelper = new THREE.GridHelper(30);
scene.add(gridHelper);

const controls = new OrbitControls(camera, renderer.domElement);

const path = new THREE.LineCurve3(
    new THREE.Vector3(-10, 0, 0), 
    new THREE.Vector3(10, 0, 0)
);

const tubeGeometry = new THREE.TubeGeometry(path, 20, 2, 5, false);
const tubeMaterial = new THREE.MeshStandardMaterial({
    color: 0x733014,
    side: THREE.DoubleSide,
    wireframe: true
});

const tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
tube.position.y = 3;
scene.add(tube);

function bendGeometry(geometry, bendAmount) {
    const positionAttribute = geometry.attributes.position;
    const vertex = new THREE.Vector3();

    for (let i = 0; i < positionAttribute.count; i++) {
        vertex.fromBufferAttribute(positionAttribute, i);

        const angle = vertex.x * bendAmount;
        const sinAngle = Math.sin(angle);
        const cosAngle = Math.cos(angle);

        const newZ = vertex.z * cosAngle - vertex.y * sinAngle;
        const newY = vertex.z * sinAngle + vertex.y * cosAngle;

        vertex.y = newY;
        vertex.z = newZ;

        positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z);
    }

    positionAttribute.needsUpdate = true;
}
const bendAmount = 0.2;
bendGeometry(tubeGeometry, bendAmount);

const tubeGeometry2 = new THREE.TubeGeometry(path, 20, 2, 5, false);
let tube2 = new THREE.Mesh(tubeGeometry2, tubeMaterial);
tube2.position.y = 3;
tube2.position.z = -10;
scene.add(tube2);

function bendIntoCircle(geometry, radius) {
    const positionAttribute = geometry.attributes.position;
    const vertex = new THREE.Vector3();

    const totalLength = geometry.parameters.path.getLength();
    for (let i = 0; i < positionAttribute.count; i++) {
        vertex.fromBufferAttribute(positionAttribute, i);

        const angle = (vertex.x / totalLength) * Math.PI * 2;

        const newX = Math.cos(angle) * radius;
        const newY = Math.sin(angle) * radius;
        const newZ = vertex.z;

        positionAttribute.setXYZ(i, newX, newY, newZ);
    }
    positionAttribute.needsUpdate = true;
}
bendIntoCircle(tubeGeometry2, 5);

function animate() {
    requestAnimationFrame(animate);

    tube.rotation.x += 0.01;
    controls.update();

    renderer.render(scene, camera);
}

animate();

Ответ или решение

Как правильно осуществить вращение тора в Three.js с внутренней стороны наружу

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

Принципы работы с Three.js

Three.js — это мощная библиотека для создания 3D-графики в браузере с использованием WebGL. Для вращения тора мы будем использовать несколько классов, таких как TorusGeometry, а также анимационные функции для создания плавного движения.

Этап 1: Создание сцены

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

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const light = new THREE.PointLight(0xffffff);
light.position.set(10, 10, 10);
scene.add(light);

Этап 2: Создание тора

Мы будем использовать TorusGeometry для создания формы тора. Здесь важно правильно задать параметры, чтобы достичь желаемого вида.

const geometry = new THREE.TorusGeometry(1, 0.4, 16, 100);
const material = new THREE.MeshStandardMaterial({ color: 0x0077ff, metalness: 0.5, roughness: 0.1 });
const torus = new THREE.Mesh(geometry, material);

scene.add(torus);

Этап 3: Анимация вращения

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

function animate() {
    requestAnimationFrame(animate);

    // Вращение тора вокруг оси Y
    torus.rotation.y += 0.01;

    // Дополнительно, для создания эффекта движения от внутренней стороны к наружной:
    // можно изменять радиус тора при вращении
    torus.scale.set(Math.sin(torus.rotation.y) + 1.5, Math.sin(torus.rotation.y) + 1.5, 1);

    renderer.render(scene, camera);
}

animate();

Этап 4: Оптимизация и дополнительные настройки

  1. Отзывчивость: Обновите camera.aspect в зависимости от размера окна для поддержания соотношения сторон.
  2. Качество: Используйте renderer.setPixelRatio(window.devicePixelRatio) для повышения качества рендеринга на высоких DPI экранах.
  3. Контролы: Для удобства управления сценой можно использовать OrbitControls:
const controls = new THREE.OrbitControls(camera, renderer.domElement);

Заключение

Этот пример показывает, как создать эффект вращения тора от внутренней стороны наружу в Three.js. Вы можете изменять параметры и добавлять дополнительные элементы, чтобы достичь желаемого эффекта. Попробуйте изменить скорость вращения или материал, чтобы сделать сцену более разнообразной. Не забывайте про необходимость тестирования на разных устройствах для обеспечения корректного отображения.

Ваша задача — наладить взаимодействие между всеми этими аспектами, чтобы получить гармоничное и визуально привлекательное завершение вашей анимации тора.

Оцените материал
Добавить комментарий

Капча загружается...