避免在 Three.js 中对已加载的 .obj 模型进行空检查
2020-05-25
110
我在 Angular 项目中使用 three.js。 我想加载一个简单的 .obj 文件并将其移动到画布上。
代码运行良好;但是我必须在 animate() 函数中明确执行空检查,以查看模型是否已加载。 如果没有空检查,控制台将记录以下内容:
TypeError: Cannot read property 'position' of null at TestComponent.animate (test.component.ts:71)
我想那是因为尚未设置实例引用,因为此时 OBJLoader 仍在忙于加载资源。
最小可验证示例:
import * as THREE from 'three';
import { OBJLoader2 } from 'three/examples/jsm/loaders/OBJLoader2.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { MtlObjBridge } from 'three/examples/jsm/loaders/obj2/bridge/MtlObjBridge.js';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css'],
})
export class TestComponent implements AfterViewInit {
@ViewChild('rendererContainer') rendererContainer: ElementRef;
renderer: THREE.WebGLRenderer;
scene = null;
camera = null;
mesh = null;
loader = null;
female = null;
constructor() {}
ngAfterViewInit() {
this.init();
this.animate();
}
init() {
this.renderer = new THREE.WebGLRenderer();
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.rendererContainer.nativeElement.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
this.scene.add(new THREE.AmbientLight(0xffffff));
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
10000
);
this.camera.position.z = 500;
this.loader = new OBJLoader2();
new MTLLoader().load('./../../assets/models/female02.mtl', (mtl) => {
this.loader.setModelName('female02');
this.loader.setLogging(true, true);
this.loader.addMaterials(
MtlObjBridge.addMaterialsFromMtlLoader(mtl),
true
);
this.loader.load(
'./../../assets/models/female02.obj',
(object3d) => {
this.female = object3d;
this.scene.add(object3d);
},
null,
null,
null
);
});
}
animate() {
if (this.female != null) { //explicit null-Check necessary
if (this.female.position.z < 250) {
this.female.translateZ(1);
}
}
window.requestAnimationFrame(() => this.animate());
this.renderer.render(this.scene, this.camera);
}
}
有没有更好的方法来操作动画循环中的对象,而不必每次都进行空检查?
2个回答
一种解决方案是在模型加载后立即开始动画。这意味着在将模型添加到场景后,立即在
onLoad()
回调中调用
animate()
。
Mugen87
2020-05-25
另一种方法是,如果您需要在加载任何内容之前触发动画循环,则用虚拟对象替换您的引用:
const nullObject= new Object3D()
let female = nullObject
let male = nullObject
let child = nullObject
//...
function onLoad( trueObject ) {
female = trueObject
}
这样,您可以期望拥有所有现有的方法和成员,但它们将是无用的。
pailhead
2020-05-25