#javascript #three.js #3d
Вопрос:
Цель
Я пытаюсь создать эллиптическую кривую (https://threejs.org/docs/#api/en/extras/curves/EllipseCurve), по которому должна перемещаться камера.
Что я сделал для достижения этой цели?
Это код для эллипса до сих пор.
var curve = new THREE.EllipseCurve(
0,0,
1, 1,
0, 2 * Math.PI,
false,
1.57
)
const points = curve.getPoints( 50 );
const geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
// Create the final object to add to the scene
var curveObject = new THREE.Line( geometry, material );
scene.add(curveObject);
Я вижу это в такой сцене:
Проблема
Я попытался повернуть кривую эллипса на 90 градусов вокруг оси x по часовой стрелке. Как я понял из документации, последний параметр определяющей функции должен вращать ее.
const curve = new THREE.EllipseCurve(
0, 0, // ax, aY
10, 10, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
Заранее благодарю вас за ваш ответ. Я совершенно новичок в Three.js так что извините, если этот вопрос может показаться глупым 😀
Комментарии:
1. Последний параметр поворачивает кривую вокруг оси Z, таким образом, сама кривая находится в плоскости XY.
Ответ №1:
поворот, поворот под углом, повлияет на локальное происхождение других настроек угла для этой кривой. Это не общее вращение эллипса, а ориентация любого смещения относительно значения по умолчанию. Другая отправная точка. Это превратило бы рот Пак-Мэна в рот Пак-Мэна наоборот в /- 180-степени. Чтобы повернуть общую кривую в мировом пространстве, используйте один из различных доступных методов, таких как curve.rotation.set(0,1,0) или вращение.y = 1. Пожалуйста, обратитесь к документации для конкретных вариантов вращения.
Ответ №2:
Найдите точку на кривой и примените к ней матрицу 4.
Вот концепция того, как вы можете это сделать (см. Строки с cam
в цикле анимации, лучше смотреть с «Полной страницы»):
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.134.0";
import {
OrbitControls
} from "https://cdn.skypack.dev/three@0.134.0/examples/jsm/controls/OrbitControls.js";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(-10, 10, 10);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
})
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let grid = new THREE.GridHelper();
grid.position.y = -5;
scene.add(grid);
let obj = new THREE.Mesh(new THREE.IcosahedronGeometry(1, 0), new THREE.MeshLambertMaterial({
color: "aqua"
}));
scene.add(obj);
let curve = new THREE.EllipseCurve(0, 0, 10, 5);
let line = new THREE.Line(new THREE.BufferGeometry().setFromPoints(curve.getSpacedPoints(100)), new THREE.LineBasicMaterial({
color: "yellow"
}));
line.rotation.x = -Math.PI * 0.25;
line.rotation.z = Math.PI * 0.125;
line.position.x = 5;
scene.add(line);
let cam = new THREE.PerspectiveCamera(25, 1, 1.5, 25);
let camHelper = new THREE.CameraHelper(cam);
scene.add(camHelper);
let clock = new THREE.Clock();
let v = new THREE.Vector3();
renderer.setAnimationLoop(() => {
let t = (clock.getElapsedTime() * 0.05) % 1;
// magic is in these lines //////////////////
cam.position.copy(curve.getPointAt(t, v));
cam.position.applyMatrix4(line.matrixWorld);
cam.lookAt(obj.position);
/////////////////////////////////////////////
renderer.clear();
renderer.setViewport(0, 0, innerWidth, innerHeight);
renderer.render(scene, camera);
renderer.setViewport(0, innerHeight - 256, 256, 256);
renderer.render(scene, cam);
})
</script>