Three.js вызывает функцию каждую секунду не кадр - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть массив векторов.И я хочу переместить объект, используя эти массивы Векторы, например, так:

animate() {

this.lorryBounds.forEach(vector => {
  this.sceneManager.boxes[0].position.set(vector)
})

this.renderer.render(this.scene, this.camera)
this.frameId = window.requestAnimationFrame(this.animate)

}

Но я пытаюсь сделать это каждую секунду, а не кадр.Я прочитал много вопросов и не нашел решения.Я пробовал THREE.Clock () и deltaTime ().Есть способ requestAnimationFrame, но я не понимаю, как его использовать в React.js.Мой файл:

    import React, { Component } from 'react'
import * as THREE from 'three'
import {SceneManager} from '../Three/SceneManager'
import Box from '../Models/Box'

class Scene extends Component {
  constructor(props) {
    super(props)

    this.start = this.start.bind(this)
    this.animate = this.animate.bind(this)
    this.Update = this.Update.bind(this)

  }

  componentDidMount() {

    const sceneManager = new SceneManager();
          sceneManager.setupLorry();
          sceneManager.calculateLorryBounds()

    const lorry = sceneManager.lorry
    const lorryBounds = sceneManager.lorryBounds


    const width = this.mount.clientWidth;
    const height = this.mount.clientHeight;

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
          camera.position.z = 20;

    const renderer = new THREE.WebGLRenderer({ antialias: true });
          renderer.setClearColor('#ffffff');
          renderer.setSize(width, height);

    //instantiate boxes
    var boxes = []
    boxes.push(new Box(1,1,1))
    boxes.push(new Box(1,2,1))
    boxes.push(new Box(2,1,1))

    sceneManager.createBoxesFromParams(boxes)
    sceneManager.boxes.forEach(element => {
      scene.add(element)
    })

    //sceneManager.boxes[0].position.set(5,-2,2)
    //console.log(sceneManager.boxes[0].position)


    scene.add(lorry);
    //get bounds
    lorry.geometry.computeBoundingBox()

    console.log(lorry.geometry.boundingBox.max)
    console.log("min bounding box : " )

    lorryBounds.forEach( vector => {
      setTimeout(() => {
        console.log(sceneManager.boxes[0].position.set(vector))
      }, 2000);

    })
    //const geometry = new THREE.BoxGeometry(10, 2, 2)
    //const geometry2 = new THREE.BoxGeometry(5, 1, 1)
    //var mat = new THREE.LineBasicMaterial( { color: 0xff2fff, linewidth: 2 } );
    //var material = new THREE.MeshBasicMaterial({color: '#FF2222'})
    //var cube = new THREE.Mesh(geometry2, material);
    //const edges = new THREE.EdgesGeometry(geometry)
    //var wireframe3 = new THREE.LineSegments( edges, mat );
    //var pivotPoint = new THREE.Object3D();



    //scene.add(wireframe3)


    //cube.add(pivotPoint);
    //scene.add(cube);



    this.scene = scene
    this.camera = camera
    this.renderer = renderer
    this.sceneManager = sceneManager
    this.lorryBounds = lorryBounds
    this.clock = new THREE.Clock();
    this.time = 0;
    this.delta = 0;
    this.speed = 1000; // units a second - 2 seconds
    this.last = 0

    this.mount.appendChild(this.renderer.domElement)
    this.start()
  }

  componentWillUnmount() {
    cancelAnimationFrame(this.frameId)
    this.mount.removeChild(this.renderer.domElement)
  }

  start() {
    if (!this.frameId) {
      this.frameId = requestAnimationFrame(this.animate)
    }
  }

  animate() {

    this.lorryBounds.forEach(vector => {
      this.sceneManager.boxes[0].position.set(vector)
    })

    this.renderer.render(this.scene, this.camera)
    this.frameId = window.requestAnimationFrame(this.animate)

  }

  render() {
    return (
      <div
        style={{ width: '100%', height: '800px' }}
        ref={(mount) => { this.mount = mount }}
      />
    )
  }
}

export default Scene

1 Ответ

0 голосов
/ 26 ноября 2018

Вы можете использовать некоторую функцию throttle для выполнения функции только один раз в секунду, в то время как ваша частота кадров намного выше.(https://www.npmjs.com/package/throttle-debounce)

var setBoxPosition = throttle(1000, function () {
    this.lorryBounds.forEach(vector => {
        this.sceneManager.boxes[0].position.set(vector)
    });
});

function animate() {

    setBoxPosition();

    this.renderer.render(this.scene, this.camera)
    this.frameId = window.requestAnimationFrame(this.animate)
}

Или вы можете использовать window.setInterval метод: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

ОБНОВЛЕНИЕ

Если вы хотите применить одинвектор каждую секунду итерируя по массиву векторов, вы можете сделать следующее:

var currentIndex = 0;
var intervalID;

function setBoxPosition() {

  this.sceneManager.boxes[0].position.set( this.lorryBounds[currentIndex] );

  if (currentIndex < this.lorryBounds.length - 1) {
    currentIndex++;
  }
  else {
    clearInterval(intervalID);
  }
}

function start() {
  if (!this.frameId) {
    this.frameId = requestAnimationFrame(this.animate)
  }

  intervalID = setInterval(setBoxPosition, 1000);
}

function animate() {
  this.renderer.render(this.scene, this.camera)
  this.frameId = window.requestAnimationFrame(this.animate)
}
...