angular - 加载时未显示 Three.js 纹理
问题描述
我在我的 Angular 应用程序中使用 Three.js。我尝试展示一个带有纹理的杯子(obj 文件)。它有效,但我只能在旋转或缩放对象时看到纹理。在它之前,对象是完全黑色的。
对象不旋转或缩放时
export class SceneComponent implements AfterViewInit {
private renderer: THREE.WebGLRenderer;
private camera: THREE.PerspectiveCamera;
private lighting;
private ambient;
private cameraTarget: THREE.Vector3;
public scene: THREE.Scene;
public fieldOfView: number = 20;
public nearClippingPane: number = 1;
public farClippingPane: number = 2000;
public controls: THREE.OrbitControls;
constructor(){
this.render = this.render.bind(this);
this.onModelLoadingCompleted = this.onModelLoadingCompleted.bind(this);
}
private get canvas(): HTMLCanvasElement {
return this.canvasRef.nativeElement;
}
private createCamera(){
let aspectRatio = this.getAspectRatio();
this.camera = new THREE.PerspectiveCamera(
this.fieldOfView,
aspectRatio,
this.nearClippingPane,
this.farClippingPane
);
// Set position and look at
this.camera.position.y = 1.5;
this.camera.position.x = 0.1;
this.camera.position.z = 4.2;
}
private createScene(){
this.scene = new THREE.Scene();
//this.scene.add(new THREE.AxesHelper(200));
var loader = new THREE.OBJLoader();
loader.load('assets/model/test.obj', this.onModelLoadingCompleted);
}
private createLight(){
this.lighting = true;
this.ambient = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(this.ambient);
this.ambient.intensity = 0.5;
var keyLight = new THREE.DirectionalLight(new THREE.Color(0xf3f3f3), 0.4);
keyLight.position.set(0, 100, 0);
this.scene.add(keyLight);
var fillLight = new THREE.DirectionalLight(new THREE.Color(0xffffff), 0.2);
fillLight.position.set(100, 0, 100);
this.scene.add(fillLight);
var backLight = new THREE.DirectionalLight(0xffffff, 0.5);
backLight.position.set(-100, 0, -100).normalize();
this.scene.add(backLight);
}
private onModelLoadingCompleted(object) {
var loader = new THREE.TextureLoader();
var material = new THREE.MeshPhongMaterial();
//material.specular = 1;
material.map = loader.load('assets/textures/y-form.png');
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
}
} );
object.position.y = -.5;
this.scene.add(object);
this.render();
console.log('Texture load complete.');
}
private getAspectRatio(): number {
let height = this.canvas.clientHeight;
if (height === 0) {
return 0;
}
return this.canvas.clientWidth / this.canvas.clientHeight;
}
private startRendering() {
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
antialias: true
});
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.renderer.setClearColor(0xffffff, 1);
let component: SceneComponent = this;
(function render() {
//requestAnimationFrame(render);
component.render();
}());
}
public render() {
this.renderer.render(this.scene, this.camera);
}
public addControls() {
this.controls = new THREE.OrbitControls(this.camera);
this.controls.enableDamping = true;
this.controls.dampingFactor = 0.7;
this.controls.enableZoom = true;
this.controls.autoRotate = false;
this.controls.autoRotateSpeed = 0.3;
this.controls.rotateSpeed = 1.0;
this.controls.zoomSpeed = 1.2;
this.controls.addEventListener('change', this.render);
}
/* EVENTS */
public onMouseDown(event: MouseEvent) {
console.log("onMouseDown");
event.preventDefault();
// Example of mesh selection/pick:
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
mouse.x = (event.clientX / this.renderer.domElement.clientWidth) * 2 - 1;
mouse.y = - (event.clientY / this.renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
var obj: THREE.Object3D[] = [];
this.findAllObjects(obj, this.scene);
var intersects = raycaster.intersectObjects(obj);
console.log("Scene has " + obj.length + " objects");
console.log("Camera position " + this.camera.position.x + ", " + this.camera.position.y + ", " + this.camera.position.z);
console.log(intersects.length + " intersected objects found")
intersects.forEach((i) => {
console.log(i.object); // do what you want to do with object
});
}
private findAllObjects(pred: THREE.Object3D[], parent: THREE.Object3D) {
// NOTE: Better to keep separate array of selected objects
if (parent.children.length > 0) {
parent.children.forEach((i) => {
pred.push(i);
this.findAllObjects(pred, i);
});
}
}
public onMouseUp(event: MouseEvent) {
console.log("onMouseUp");
}
@HostListener('window:resize', ['$event'])
public onResize(event: Event) {
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
console.log("onResize: " + this.canvas.clientWidth + ", " + this.canvas.clientHeight);
this.camera.aspect = this.getAspectRatio();
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.render();
}
@HostListener('document:keypress', ['$event'])
public onKeyPress(event: KeyboardEvent) {
console.log("onKeyPress: " + event.key);
}
/* LIFECYCLE */
ngAfterViewInit() {
this.createScene();
this.createLight();
this.createCamera();
this.startRendering();
this.addControls();
}
}
当我删除纹理时,对象显示正确.. 感谢您的帮助。
解决方案
问题是您过早地重绘场景。尝试使用的onLoad()
回调,TextureLoader
以便this.render();
仅在纹理完全加载时执行
或者,考虑使用THREE.LoadingManager来管理多个加载器的请求。
推荐阅读
- c++ - 如何降低此代码的时间复杂度以找到二进制数组中连续 1 的最大数量?
- ruby-on-rails - 如何在 Rail 的 haml 文件中用大量新行声明变量?
- python - python-print在启动时不在控制台上显示输出
- swift - 如何对使用 Promise Kit 的异步函数进行单元测试
- angular - 如何在单击角度11中的按钮时在http get调用中传递参数
- .net - 我想在一个 .net5 项目中使用两个不同的 kafka 主题
- flutter - Flutter FCM 工作一段时间然后停止工作
- html - 如何在不使用 jinja {{form}} 模板的情况下将数据从任何自定义 HTML 表单发送到 Django 模型表单
- azure-log-analytics - 在 Azure 中,想要将 Windows 虚拟机的日志发送到 2 个不同的 Logs Workspace
- php - Laravel:auth()->user() 手动登录后返回 null