Я пытался искать с этим и иду пустым. Я изучаю ThreeJS (используя r102) для удовольствия, и у меня возникают проблемы с получением функций панорамирования и поворота TrackballControl для правильной работы. Хотя управление масштабированием работает отлично.
Я не использую модуль узла three
, поскольку полезные вспомогательные классы, которые были перемещены из ядра, не являются модулями и не работают в Vue (в моем случае Nuxt) из-за загрязнения глобального пространства имен. Я начал использовать модуль узла three-full
для обучения ThreeJS, поскольку он содержит переписанные примеры, перенесенные из базовой библиотеки.
Я пробовал TrackballControls в three-full
, а также узлы three-trackballcontrols
и панорамирование и поворот не работают ни в одном из них. У меня нет никаких ошибок, просто ничего не происходит, когда я пытаюсь перемещаться и поворачиваться.
Вот мой единственный файл vue, в котором я просто вручную создаю некоторые геометрии и "анимирую" их положение с помощью цикла RAF.
<template>
<section class="section">
<div class="hero is-fullheight">
<div
id="three-element"
ref="threeElement"
@click="addManualGeometry"/>
<button @click="startScene">Start</button>
</div>
</section>
</template>
<script>
import * as THREE from "three-full";
export default {
components: {},
data() {
return {
scene: undefined,
camera: undefined,
renderer: undefined,
stats: undefined,
plane: undefined,
planeDimensions: [60, 40],
objectCount: 0,
started: false,
step: 0,
trackballControls: undefined,
clock: undefined
};
},
mounted() {
console.log(THREE);
this.setup();
//this.addPlane();
this.addLight();
this.addManualGeometry();
this.positionCamera();
this.setupClock();
this.setupTrackballControls();
this.$refs.threeElement.appendChild(this.renderer.domElement);
},
methods: {
setup() {
// set up scene, camera, renderer, and axes
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setClearColor(new THREE.Color(0x000000));
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMapSoft = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
window.addEventListener("resize", this.handleWindowResize);
},
handleWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
},
addPlane() {
// create plane geometry and material
const planeGeometry = new THREE.PlaneGeometry(
this.planeDimensions[0],
this.planeDimensions[1],
1,
1
);
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xaaaaaa });
this.plane = new THREE.Mesh(planeGeometry, planeMaterial);
this.plane.rotation.x = -0.5 * Math.PI;
this.plane.position.set(15, 0, 0);
this.plane.receiveShadow = true;
// add plane to the scene
this.scene.add(this.plane);
},
addManualGeometry() {
const vertices = [
new THREE.Vector3(1, 3, 1),
new THREE.Vector3(1, 3, -1),
new THREE.Vector3(1, -1, 1),
new THREE.Vector3(1, -1, -1),
new THREE.Vector3(-1, 3, -1),
new THREE.Vector3(Math.random(), Math.random(), 1),
new THREE.Vector3(-1, Math.random(), -1),
new THREE.Vector3(-1, -1, 1)
];
const faces = [
new THREE.Face3(0, 2, 1),
new THREE.Face3(2, 3, 1),
new THREE.Face3(4, 6, 5),
new THREE.Face3(6, 7, 5),
new THREE.Face3(4, 5, 1),
new THREE.Face3(5, 0, 1),
new THREE.Face3(7, 6, 2),
new THREE.Face3(6, 3, 2),
new THREE.Face3(5, 7, 0),
new THREE.Face3(7, 2, 0),
new THREE.Face3(1, 3, 4),
new THREE.Face3(3, 6, 4)
];
const geom = new THREE.Geometry();
geom.vertices = vertices;
geom.faces = faces;
// this makes threejs determine a normal vector for each of the faces
geom.computeFaceNormals();
const materials = [
new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true }),
new THREE.MeshLambertMaterial({
opacity: 0.9,
color: Math.random() * 0x44ff44,
transparent: true
})
];
const mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
mesh.castShadow = true;
mesh.children.forEach(child => {
child.castShadow = true;
});
this.scene.add(mesh);
},
updateGeometryRotation(shape, coords) {
shape.rotation.x += coords[0];
shape.rotation.y += coords[1];
shape.rotation.z += coords[2];
},
addLight() {
// add spotlight and ambient light
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024);
spotLight.shadow.camera.far = 130;
spotLight.shadow.camera.near = 40;
spotLight.castShadow = true;
spotLight.decay = 2;
spotLight.penumbra = 0.05;
this.scene.add(spotLight);
const ambientLight = new THREE.AmbientLight(0x3c3c3c);
this.scene.add(ambientLight);
},
positionCamera() {
// position the camera for the scene
this.camera.position.set(-30, 40, 30);
this.camera.lookAt(this.scene.position);
},
setupClock() {
this.clock = new THREE.Clock();
},
setupTrackballControls() {
this.trackballControls = new THREE.TrackballControls(
this.camera,
this.renderer.domElement
);
},
renderScene() {
const rotationArray = [0.02, 0.02, 0.02];
this.trackballControls.update(this.clock.getDelta());
this.scene.traverse(obj => {
if (obj instanceof THREE.Mesh && obj !== this.plane) {
obj.rotation.x *= Math.random() * 0.002;
obj.rotation.y *= Math.random() * 0.002;
obj.translateX(Math.random() * 0.04);
obj.rotation.z += Math.random() * 0.04;
}
});
window.RAF = requestAnimationFrame(this.renderScene);
this.renderer.render(this.scene, this.camera);
},
startScene() {
if (this.started) return;
this.renderScene();
this.started = !this.started;
}
}
};
</script>
<style scoped>
button {
position: absolute;
top: 10px;
left: 0;
right: 0;
margin: auto;
display: block;
width: 80px;
background: red;
color: white;
border-color: transparent;
border-radius: 10px;
outline: unset;
}
</style>
Вот исходный код TrackballControls из three-full
. Мне непонятно, почему масштабирование будет работать, но не панорамирование или поворот, и, поскольку я нуб ThreeJS, копающийся в исходном коде TrackballControls, в данный момент мне не по плечу. Если это представляет какой-либо интерес, вот репозиторий github, который я делаю с этими демонстрациями в . Данный файл находится в pages/learn-threejs-book/manual-geometry.vue
.
У кого-нибудь есть советы по этому поводу? У вас были TrackballControls, работающие в Vue или React раньше? Я чувствую, что у есть , чтобы быть просто проблемой с моей стороны, но я не уверен, что.
Обновление:
Мне удалось добавить код, найденный в старой проблеме с github, чтобы вручную повернуть камеру следующим образом:
changeCameraPosition(e) {
e.preventDefault();
e.stopPropagation();
const theta = 0.1; //the speed of rotation
console.log(e);
if (e.key === "a") {
const x = this.camera.position.x;
const z = this.camera.position.z;
console.log(this.camera);
this.camera.position.x = x * Math.cos(theta) + z * Math.sin(theta);
this.camera.position.z = z * Math.cos(theta) - x * Math.sin(theta);
this.camera.lookAt(this.scene.position);
}
},
Я бы очень хотел использовать TrackballControls, который поставляется с ThreeJS, но пока это будет работать для моего случая.