При перетаскивании мышью группа уже повернута, и для .rotation
установлено определенное значение.THREE.Euler.set()
отменяет текущий оборот и устанавливает совершенно новый.Это приводит к тому, что поворот возвращается к исходной ориентации.
Новый поворот должен быть применен к существующему повороту.Распространенным способом является вычисление матрицы вращения для нового вращения.Затем примените новое вращение к текущей матрице.Результатом является вращение, которое необходимо установить для группы.
rotation = new_rotation * current_rotation
В THREE.js .rotation
является THREE.Euler
объектом -См. Углы Эйлера .
Matrix4.makeRotationFromEuler
можно преобразовать углы формы Эйлера в матрицу вращения 4x4.
С Matrix4.multiplyMatrices
, 2 матрицы могут
И Euler.setFromRotationMatrix
может преобразовать матрицу вращения 4x4 в углы Эйлера
Получить текущую матрицу вращения из группы:
let currentRotation = new THREE.Matrix4();
currentRotation.makeRotationFromEuler(group.rotation);
Настройкаматрица вращения с новым компонентом вращения по углам Эйлера:
let newEuler = new THREE.Euler(0, (event.pageX - startX) / 900, 0);
let newRotation = new THREE.Matrix4();
newRotation.makeRotationFromEuler(newEuler);
Применить новое вращение к текущему вращению:
let finalRotation = new THREE.Matrix4();
finalRotation.multiplyMatrices(newRotation, currentRotation);
Установить окончательное и составное вращение для группы
group.rotation.setFromRotationMatrix(finalRotation);
Поскольку вращение применяется к группе, startX
и startY
должны быть установлены в текущее положение мыши:
startX = event.pageX;
startY = event.pageY;
Окончательное событие "mousemove":
document.addEventListener("mousemove", function (event) {
if (isMouseDown) {
document.body.style.cursor = 'grabbing'
}
if(isMouseDown) {
let currentRotation = new THREE.Matrix4();
currentRotation.makeRotationFromEuler(group.rotation);
let newEuler = new THREE.Euler(0, (event.pageX - startX) / 900, 0);
let newRotation = new THREE.Matrix4();
newRotation.makeRotationFromEuler(newEuler);
let finalRotation = new THREE.Matrix4();
finalRotation.multiplyMatrices(newRotation, currentRotation);
group.rotation.setFromRotationMatrix(finalRotation);
startX = event.pageX;
startY = event.pageY;
}
})
Я применил предложения к вашему исходному коду.Смотрите пример:
doThree = function () {
console.clear();
const renderer = new THREE.WebGLRenderer({
anitalias: true
})
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setClearColor(0x000000, 1)
const section = document.getElementById('container');
section.appendChild(renderer.domElement)
// Scene -------------------------------------------------------
const scene = new THREE.Scene()
scene.fog = new THREE.FogExp2(0x000000, 0.00034)
// Light -------------------------------------------------------
const light = new THREE.AmbientLight(0xcccccc)
scene.add(light)
//const light2 = new THREE.PointLight(0xcccccc, .75, 0)
const light2 = new THREE.DirectionalLight(0xffffff, 0.5)
light2.position.set(-1000, 0, -3000)
scene.add(light2)
const light3 = new THREE.DirectionalLight(0xffffff, 0.5)
light3.position.set(1000, 0, -3000)
scene.add(light3)
// Camera ------------------------------------------------------
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 10000)
camera.position.z = -2500
// Texture Loader ----------------------------------------------
const loader = new THREE.TextureLoader()
// Shapes ------------------------------------------------------
var mirrorCube, mirrorCubeCamera; // for mirror material
var mirrorSphere, mirrorSphereCamera; // for mirror material
function init () {
var cubeGeom = new THREE.PlaneGeometry(10000, 12000, 120);
mirrorCubeCamera = new THREE.CubeCamera( 0.1, 10000, 1080 );
mirrorCubeCamera.position.set(0, 1500, 05)
scene.add( mirrorCubeCamera );
var mirrorCubeMaterial = new THREE.MeshBasicMaterial( { envMap: mirrorCubeCamera.renderTarget.texture } );
mirrorCube = new THREE.Mesh( cubeGeom, mirrorCubeMaterial );
mirrorCube.position.set(0, -550, -1000)
mirrorCube.rotation.x = -90 * Math.PI / 180;
scene.add(mirrorCube);
}
init()
const createFNUP = function (color, x, y, z) {
const geometry = new THREE.PlaneGeometry( 943, 512, 120)
const material = new THREE.MeshPhongMaterial({
color: color,
specular: 0x111111,
shininess: 0,
side: THREE.DoubleSide,
transparent: true,
})
const mesh = new THREE.Mesh(geometry, material)
mesh.position.set(x,y,z)
scene.add(mesh)
return mesh
}
const addFloor = function (color) {
const geometry = new THREE.PlaneGeometry(10000, 10000, 120)
const material = new THREE.MeshPhongMaterial({
color: color,
side: THREE.DoubleSide
})
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
return mesh
}
// Adding Shapes -----------------------------------------------
const fnup = createFNUP(0xffffff, 1100, 50, 0)
const old = createFNUP(0xff0000, -1100, 50, 0)
const cam = createFNUP(0x00ff00, 0, -100, 1000)
const alex = createFNUP(0x0000ff, -0, 200, -1000)
const roof = addFloor(0x232323)
roof.position.z = 2000
const group = new THREE.Group()
group.add(fnup, old, cam, alex)
scene.add(group)
// Holding Camera Position for tweening ------------------------
let currentX = 0
let currentY = 0
let aimX = 0
let aimY = 0
let aimX2 = 0
let aimY2 = 0
// Holding data about the shapes
const shapes = []
// Animate -----------------------------------------------------
let oldRotate = true
let camRotate = true
let groupRotate = true
let fnupPosition = true
let projectHov = true
function animate() {
const diffX = aimX - currentX
const diffY = aimY - currentY
const diffX2 = aimX2 - currentX
const diffY2 = aimY2 - currentY
currentX = currentX + diffX * 0.1
currentY = currentY + diffY * 0.1
camera.position.x = currentX
camera.position.y = currentY
group.rotateY(0.003)
camera.lookAt(scene.position)
mirrorCubeCamera.lookAt(scene.position)
mirrorCube.visible = false;
mirrorCubeCamera.update( renderer, scene );
mirrorCube.visible = true;
renderer.render(scene, camera)
requestAnimationFrame(animate)
}
animate ()
// Variables ---------------------------------------------------
let isMouseDown = false
let startX = 0
let startY = 0
// Functions ---------------------------------------------------
document.addEventListener("mousedown", function () {
isMouseDown = true
startX = event.pageX
startY = event.pageY
document.body.style.cursor = 'grabbing';
})
document.addEventListener("mouseup", function () {
isMouseDown = false
document.body.style.cursor = 'grab';
})
document.addEventListener("mousemove", function (event) {
if (isMouseDown) {
document.body.style.cursor = 'grabbing'
}
if(isMouseDown) {
let currentRotation = new THREE.Matrix4();
currentRotation.makeRotationFromEuler(group.rotation);
let newEuler = new THREE.Euler(0, (event.pageX - startX) / 900, 0);
let newRotation = new THREE.Matrix4();
newRotation.makeRotationFromEuler(newEuler);
let finalRotation = new THREE.Matrix4();
finalRotation.multiplyMatrices(newRotation, currentRotation);
group.rotation.setFromRotationMatrix(finalRotation);
startX = event.pageX;
startY = event.pageY;
}
})
window.addEventListener("resize", function () {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
}
doThree()
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<div id="container"></div>