Поворот группы в three.js, но она сбрасывается в исходное начальное положение мышью вниз - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь повернуть вращение группы в three.js, я могу заставить ее вращаться, но всякий раз, когда вы пытаетесь повернуть группу снова, она сбрасывает себя из исходного исходного положения.Я уверен, что это легко исправить, но я не могу найти его.Любая помощь будет оценена.

Вот ссылка на мою скрипку: https://jsfiddle.net/jacob_truax/bw3pmLk1/59/

Вот код, который я реализовал для анимации движения.

  let isMouseDown = false
  let startX = 0
  let startY = 0

  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'
    }

    aimX = ((window.innerWidth / 2) - event.pageX) * 0.35
    aimY = ((window.innerHeight / 2) - event.pageY) * 0.5


    if(isMouseDown) {
      aimX = aimX + (event.pageX - startX)
      aimY = aimY + (event.pageY - startY)
      group.rotation.set(0, ((aimX + (event.pageX - startX)) + (aimY 
+ (event.pageY - startY))) / 900, 0)
    }
  })

1 Ответ

0 голосов
/ 03 февраля 2019

При перетаскивании мышью группа уже повернута, и для .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>
...