我在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
答案 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();
。