使用未定义的摄像头调用的WebGLRenderer.render

时间:2016-09-24 18:18:05

标签: three.js

我在3D应用程序中组合使用了three.js和OrbitControls.js。有时使用未定义的摄像头调用WebGLRenderer.render。当我使用鼠标导航3D模型时,会发生这种情况,使用OrbitConrols提供的控件。 未定义的相机参数很奇怪,因为我的animate函数(请参阅下面的代码)始终使用定义良好的相机调用WebGLRenderer.render。此外,在实例化OrbitControls时,我给它一个定义良好的相机。所以问题是 - WebGLRenderer.render怎么可能在未定义的相机调用?{/ p>

注意:WebGLRenderer.render函数的源代码可以在three.js源代码的line 20426中看到。

我尝试通过搜索文本字符串render(找到所有潜在的呼叫网站。字符串render(上有14个这样的匹配,但这些匹配都没有将未定义的摄像头作为参数。因此,这条路很冷。

我尝试了来自被调用者(WebGLRenderer.render函数的函数体)的堆栈跟踪,但这只是回到了一些mix-it-all事件中心。但它给了我一个提示,调用者可能是Javascript本身,从它的DOM事件系统调用。这可以解释为什么我在three.js源代码中找不到调用站点。

因此,问题可能与OrbitControls与Javascript事件系统交互的点有关。在初始化我的应用程序时,我在OrbitControls实例上注册了一个事件。见下面的代码。这可能会造成麻烦吗?当发生这种情况时,没有给出相机作为参数:/

var myControls = require('../../instances/three/myControls');
var myRenderer = require('../../instances/three/myRenderer');

myControls.damping = 0.2;
myControls.domElement.addEventListener( 'change', myRenderer.render );

编辑: 我正在使用这些版本:

three.js 0.81.0
three-orbit-controls 72.0.0

1 个答案:

答案 0 :(得分:0)

所以,确实对render的错误调用来自某个事件系统(Javascript DOM事件系统)。此模块显示render函数作为回调事件监听器的位置:

var myControls = require('../../instances/three/myControls');
var myRenderer = require('../../instances/three/myRenderer');

myControls.damping = 0.2;
myControls.addEventListener( 'change', myRenderer.render );

module.exports = {};

myControls模块看起来像这样:

var THREE = require('three');
var orbitControls = require('three-orbit-controls');
var myRenderer = require('../../instances/three/myRenderer');
var myCamera = require('./myCamera');
require('../../sideeffects/three/addCamera');

// add orbitControls to THREE:
var OrbitControls = orbitControls( THREE );

// make controls:
var controls = new OrbitControls( myCamera, myRenderer.domElement );

module.exports = controls;

但是,似乎OrbitControls.js的更改方式使OrbitControls构造函数的实例不再是DOM元素。因此,一个人不能在他们身上注册事件,正如我在线上所做的那样:

myControls.addEventListener( 'change', myRenderer.render );

相反,OrbitControls构造函数的实例有一个新属性:domElement,正如您可能已经猜到的那样,它确实是一个DOM元素。因此,我可以通过将事件附件的目标更改为myControls.domElement来解决问题。因此,上面的行看起来像这样:

myControls.domElement.addEventListener( 'change', myRenderer.render );

这解决了问题:)

编辑: 事实证明,这条线实际上可以完全省略!只有在没有动画循环(每个循环步骤调用requestAnimationFrame的永久循环)时才需要它。

此外,可以通过以下方式启用阻尼:

myControls.enableDamping = true;

然后在动画循环中的某处添加myControls.update();