如何让两个Three-JS对象同时运行并设置动画?

时间:2018-12-25 23:27:51

标签: javascript three.js

我已经创建了两个3JS对象和场景用于学习目的。两者都放在单独的PHP文件中(不在jsfiddle中)。但是,我无法弄清楚为什么通过添加第二个对象,第一个对象会停止设置动画并且不再运行?我该如何弄清楚为什么我的对象互相抵消,以及如何创建两个不同或更多的同时进行动画处理的Three.js项目?

// GRID OBJ是第一个对象,第二个是// BALL 当我删除第二个调用3js ball的脚本时,网格将进行动画处理,添加球后,网格将停止动画,只有球可以动画。

http://jsfiddle.net/tdqh4jno/

//GRID OBJ
var container = document.getElementById('grid')

var vertexHeight = 90,
  planeDefinition = 25,
  planeSize = 900,
  totalObjects = 1,
  background = "#002135",
  meshColor = "#ff3057";

var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;

var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor( 0x000000, 0 );

var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);

var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  color: meshColor,
  wireframe: true
}));
plane.rotation.x -= Math.PI * .5;

scene2.add(plane);

renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(background, 1);
container.appendChild(renderer.domElement);

function updatePlane() {
  for (var i = 0; i < planeGeo.vertices.length; i++) {
    planeGeo.vertices[i].z += Math.random() * vertexHeight;
    planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
  }

};

var count = 0

function renderGrid() {
  var gridSpeed = 0.4;
  var gridInterlop = -0.4;
  var gridWaveSpeed = 0.003;  
  var gridWaveHeight = 0.00003;

  requestAnimationFrame(renderGrid);

  for (var i = 0; i < planeGeo.vertices.length; i++) {
    var z = +planeGeo.vertices[i].z;
    planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
    plane.geometry.verticesNeedUpdate = true;
    count += gridInterlop
  }

  renderer.render(scene2, camera2);

}

updatePlane();
renderGrid();


//BALL ITEM
	var camera2 = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
  var renderer = new THREE.WebGLRenderer();
  renderer.autoClear = false;
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  var sceneTop = new THREE.Scene(); // initialising the scene
  sceneTop.background = new THREE.Color( 0x08080c);


  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(100,100,100);
  spotLight.castShadow = false;
  sceneTop.add(spotLight);

  function Mat(){
    var material = new THREE.MeshPhongMaterial({
      color      : new THREE.Color(0xff3266),
      emissive   : new THREE.Color(0x08080c),
      specular   : new THREE.Color(0x08080c),

      shininess  : 0,
      wireframe  : true,
      transparent: 0.5,
      opacity    : 0.55
    });
    return material;
  }

  var geometry = new THREE.IcosahedronGeometry(45 , 1);
  var obj = new THREE.Mesh(geometry, Mat());


  sceneTop.add(obj);

  camera2.position.z = 90;

  function myrender(){
    renderer.setClearColor( 0x000000, 0 );

    obj.rotation.x += 0.0004;
    obj.rotation.y += 0.0006;
    obj.rotation.z += Math.random() * 0.0005;
    renderer.render(sceneTop, camera2);
    requestAnimationFrame(myrender);
  }



  window.addEventListener('resize', onWindowResize, true);

  function onWindowResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera2.updateProjectionMatrix();
};


    myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>

1 个答案:

答案 0 :(得分:1)

您创建2个THREE.WebGLRenderer对象,但两个对象均分配给变量renderer。这会破坏函数renderGrid中第一个(网格)对象的动画。

在您的代码中创建了2个不同的场景,这些场景由2个不同的变量(sceneTopscene2)引用。还要创建2个不同的渲染对象,并由2个不同的变量(rendererrenderer2)引用:

var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );

// [...]

renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);

function renderGrid() {

    // [...]

    renderer2.render(scene2, camera2);
}

在下面您必须注意,renderer分别对应于camera sceneTop,而renderer2对应于scene2camera2

var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);

[...]

camera.position.z = 90;

function myrender(){

    // [...]    

    renderer.render(sceneTop, camera);
    requestAnimationFrame(myrender);
}

请参见示例,其中我将建议的更改应用于原始代码:

//GRID OBJ
var container = document.getElementById('grid')

var vertexHeight = 90,
  planeDefinition = 25,
  planeSize = 900,
  totalObjects = 1,
  background = "#002135",
  meshColor = "#ff3057";

var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;

var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );

var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);

var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  color: meshColor,
  wireframe: true
}));
plane.rotation.x -= Math.PI * .5;

scene2.add(plane);

renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);

function updatePlane() {
  for (var i = 0; i < planeGeo.vertices.length; i++) {
    planeGeo.vertices[i].z += Math.random() * vertexHeight;
    planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
  }

};

var count = 0

function renderGrid() {
  var gridSpeed = 0.4;
  var gridInterlop = -0.4;
  var gridWaveSpeed = 0.003;  
  var gridWaveHeight = 0.00003;

  requestAnimationFrame(renderGrid);

  for (var i = 0; i < planeGeo.vertices.length; i++) {
    var z = +planeGeo.vertices[i].z;
    planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
    plane.geometry.verticesNeedUpdate = true;
    count += gridInterlop
  }

  renderer2.render(scene2, camera2);
}

updatePlane();
renderGrid();


//BALL ITEM
	var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
  
  var renderer = new THREE.WebGLRenderer();
  renderer.autoClear = false;
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  var sceneTop = new THREE.Scene(); // initialising the scene
  sceneTop.background = new THREE.Color( 0x08080c);


  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(100,100,100);
  spotLight.castShadow = false;
  sceneTop.add(spotLight);

  function Mat(){
    var material = new THREE.MeshPhongMaterial({
      color      : new THREE.Color(0xff3266),
      emissive   : new THREE.Color(0x08080c),
      specular   : new THREE.Color(0x08080c),

      shininess  : 0,
      wireframe  : true,
      transparent: 0.5,
      opacity    : 0.55
    });
    return material;
  }

  var geometry = new THREE.IcosahedronGeometry(45 , 1);
  var obj = new THREE.Mesh(geometry, Mat());

  sceneTop.add(obj);

  camera.position.z = 90;

  function myrender(){
    renderer.setClearColor( 0x000000, 0 );

    obj.rotation.x += 0.0004;
    obj.rotation.y += 0.0006;
    obj.rotation.z += Math.random() * 0.0005;
    renderer.render(sceneTop, camera);
    requestAnimationFrame(myrender);
  }

  window.addEventListener('resize', onWindowResize, true);

  function onWindowResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer2.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight; 
    camera.updateProjectionMatrix();
    camera2.aspect = window.innerWidth / window.innerHeight; 
    camera2.updateProjectionMatrix();
};

myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>


或者,两个场景都可以渲染到视口的不同部分。

创建1个THREE.WebGLRenderer,并将.autoClear属性设置为false

var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);

同时渲染两个场景视口的2个不同部分。视口矩形可以通过.setViewport进行更改:

function myrender(){

    // [...]

    renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
    renderer.clear();

    renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
    renderer.render(sceneTop, camera, 0, false);

    renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
    renderer.render(scene2, camera2, 0, false);

    requestAnimationFrame(myrender);
}

确保仅为首先呈现的.background设置THREE.Scene属性。

请参见示例:

//GRID OBJ
var container = document.getElementById('grid')

var vertexHeight = 90,
  planeDefinition = 25,
  planeSize = 900,
  totalObjects = 1,
  background = "#002135",
  meshColor = "#ff3057";

var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);

var camera2 = new THREE.PerspectiveCamera( 110, window.innerWidth/2/window.innerHeight, 5)
camera2.position.y = 500;

var scene2 = new THREE.Scene();

var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);

var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  color: meshColor,
  wireframe: true
}));
plane.rotation.x -= Math.PI * .5;

scene2.add(plane);


function updatePlane() {
  for (var i = 0; i < planeGeo.vertices.length; i++) {
    planeGeo.vertices[i].z += Math.random() * vertexHeight;
    planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
  }

};

var count = 0

updatePlane();

//BALL ITEM
	var camera = new THREE.PerspectiveCamera(100, window.innerWidth/2/window.innerHeight, 0.1, 1000);

  var sceneTop = new THREE.Scene(); // initialising the scene
  sceneTop.background = new THREE.Color( 0x08080c);

  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(100,100,100);
  spotLight.castShadow = false;
  sceneTop.add(spotLight);

  function Mat(){
    var material = new THREE.MeshPhongMaterial({
      color      : new THREE.Color(0xff3266),
      emissive   : new THREE.Color(0x08080c),
      specular   : new THREE.Color(0x08080c),

      shininess  : 0,
      wireframe  : true,
      transparent: 0.5,
      opacity    : 0.55
    });
    return material;
  }

  var geometry = new THREE.IcosahedronGeometry(45 , 1);
  var obj = new THREE.Mesh(geometry, Mat());

  sceneTop.add(obj);

  camera.position.z = 90;

  function myrender(){
    var gridSpeed = 0.4;
    var gridInterlop = -0.4;
    var gridWaveSpeed = 0.003;  
    var gridWaveHeight = 0.00003;
    for (var i = 0; i < planeGeo.vertices.length; i++) {
      var z = +planeGeo.vertices[i].z;
      planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
      plane.geometry.verticesNeedUpdate = true;
      count += gridInterlop
    }

    obj.rotation.x += 0.0004;
    obj.rotation.y += 0.0006;
    obj.rotation.z += Math.random() * 0.0005;

    renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
    renderer.clear();

    renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
    renderer.render(sceneTop, camera, 0, false);
    
    renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
    renderer.render(scene2, camera2, 0, false);
    
    requestAnimationFrame(myrender);
  }

  window.addEventListener('resize', onWindowResize, true);

  function onWindowResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / 2 / window.innerHeight; 
    camera.updateProjectionMatrix();
    camera2.aspect = window.innerWidth / 2 / window.innerHeight; 
    camera2.updateProjectionMatrix();
};

myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>