How to apply multiple textures to GLTF models? - three.js

I tried to apply the texture to the model, but it works only in the case of a single texture. With multiple textures, the model is not displayed.
Sample code with a single texture:
loader = new THREE.GLTFLoader().setPath('models3/');
const textureLoader = new THREE.TextureLoader();
loader.load('01-Fundament-002.gltf', function (gltf) {
var model = gltf.scene;
model.traverse ( ( o ) => {
if ( o.isMesh ) {
o.material.map = textureLoader.load('models3/Beton OsnovaVRay-DiffuseShadowMap-Edit.png');
}
} );
scene.add(model);
});
Sample code with a multiple texture:
loader = new THREE.GLTFLoader().setPath('models3/');
const textureLoader = new THREE.TextureLoader();
loader.load('01-Fundament-002.gltf', function (gltf) {
var model = gltf.scene;
model.traverse ( ( o ) => {
if ( o.isMesh ) {
const materials = [
new THREE.MeshBasicMaterial({map: textureLoader.load('models3/1.png')}),
new THREE.MeshBasicMaterial({map: textureLoader.load('models3/2.png')}),
new THREE.MeshBasicMaterial({map: textureLoader.load('models3/3.png')}),
new THREE.MeshBasicMaterial({map: textureLoader.load('models3/4.png')}),
];
o.material = materials;
}
} );
scene.add(model);
});

You cannot assign an array to the material. I think you are confusing it with cube texture. This should work assuming your model is made out of 4 meshes only.
var i = 1;
loader = new THREE.GLTFLoader().setPath('models3/');
const textureLoader = new THREE.TextureLoader();
loader.load('01-Fundament-002.gltf', function (gltf) {
var model = gltf.scene;
model.traverse ( ( o ) => {
if ( o.isMesh ) {
o.material = new THREE.MeshBasicMaterial({map: textureLoader.load(`models3/${i++}.png`)});
}
});
scene.add(model);
});

Related

how to resolve (reading 'elements') error while using FBXLoader()

I get Uncaught TypeError: Cannot read properties of undefined (reading 'elements') error and can't see my wheel and plane with a shadow texture on the floor:
Here's my code:
const loader = new FBXLoader();
#foreach ($files as $file)
#if (strtolower(pathinfo($file, PATHINFO_EXTENSION)) == 'fbx')
loader.setResourcePath('storage/models/{{ $modelId }}/').load('storage/{{ $file }}', function ( object ) {
object.traverse( function ( child ) {
if ( child.isMesh ) {
if ( child instanceof THREE.Mesh ) {
// child.material.color.setRGB (1, 0, 0);
child.material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
map: child.material.map
} );
}
}
} );
object.receiveShadow = true;
object.castShadow = true;
scene.add( object );
} );
#endif
#endforeach
here's how this car should looks like:

Reflection between objects ( three.js & gltf2 )

Good evening. I am export two models from Blender 2.79 to three.js.
Scene: link
Shadows work. Objects reflect the world around them but do not reflect among themselves.
Scene code:
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, -8, 2 );
// envmap
var path = '/textures/sky_glTF/pisa/'; // ADD "/"
var format = '.png';
var envMap = new THREE.CubeTextureLoader().load( [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
] );
scene = new THREE.Scene();
scene.background = envMap;
//MR - YES mirror
var loader = new THREE.GLTFLoader();
loader.load( '/gltf/1.gltf', function ( gltf ) {
gltf.scene.traverse( function ( node ) {
if ( node.isMesh || node.isLight ) node.castShadow = true;
if ( node.isMesh || node.isLight ) node.receiveShadow = true;
} );
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
child.material.envMap = envMap;
}
} );
gltf.scene.position.x = 0;
gltf.scene.position.y = 0;
gltf.scene.position.z = 0;
scene.add( gltf.scene );
} );
//MR - YES mirror
var loader = new THREE.GLTFLoader();
loader.load( '/gltf/2.gltf', function ( gltf2 ) {
gltf2.scene.traverse( function ( node ) {
if ( node.isMesh || node.isLight ) node.castShadow = true;
if ( node.isMesh || node.isLight ) node.receiveShadow = true;
} );
gltf2.scene.traverse( function ( child ) {
if ( child.isMesh ) {
child.material.envMap = envMap;
}
} );
gltf2.scene.position.x = 0;
gltf2.scene.position.y = 0;
gltf2.scene.position.z = 0;
scene.add( gltf2.scene );
} );
How to implement reflections between objects?
What part of the code do you still have to show for a complete answer to my question?

How to cast a shadow with a gltf model in three.js?

Hey there i'm new to three js & was wondering how to cast a shadow with a gltf model?
I can see it's possible as it's working here
I assume i'm not structuring my code correctly-
var model = new THREE.GLTFLoader();
model.load('https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf', function(gltf) {scene.add(gltf.scene);});
model.castShadow = true;
Here's the fiddle https://jsfiddle.net/steveham/ckpfwy24/87/
Cheers!
You need to set castShadow = true on each child mesh, like so:
var loader = new THREE.GLTFLoader();
loader.load( 'https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf', function( gltf ) {
gltf.scene.traverse( function( node ) {
if ( node.isMesh ) { node.castShadow = true; }
} );
scene.add( gltf.scene );
} );
three.js r.113
var loader = new THREE.GLTFLoader();
loader.load( 'file path/gltf.gltf', function ( gltf ) {
gltf.scene.traverse( function ( node ) {
if ( node.isMesh || node.isLight ) node.castShadow = true;
if ( node.isMesh || node.isLight ) node.receiveShadow = true;
} );
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
child.material.envMap = envMap; //reflection of the world
}
} );
scene.add( gltf.scene );

Camera Autorotate threejs

How can I make camera to autorotate when i hit any obstacle in threejs. I referred the following link
http://threejs.live/#/webgl_raymarching_reflect
where the rendering restarts when it hits any obstacle. I tried implementing in my project but that doesn't works. How can i implement that in my project?
My map.ts code is
private renderer: THREE.WebGLRenderer;
private camera: THREE.PerspectiveCamera;
public scene: THREE.Scene;
public fieldOfView: number = 10;
public nearClippingPane: number = 1;
public farClippingPane: number = 1000;
public controls: THREE.OrbitControls;
#ViewChild('canvas')
private canvasRef: ElementRef;
constructor(public loadingCtrl: LoadingController) {
this.render = this.render.bind(this);
this.onModelLoadingCompleted = this.onModelLoadingCompleted.bind(this);
}
private get canvas(): HTMLCanvasElement {
return this.canvasRef.nativeElement;
}
private createScene() {
this.scene = new THREE.Scene();
var loader = new THREE.ColladaLoader();
loader.load('assets/Buildings/Block.DAE', this.onModelLoadingCompleted);
}
private onModelLoadingCompleted(collada) {
const loading = this.loadingCtrl.create({
content:'Loading Please Wait...'
});
loading.present();
var modelScene = collada.scene;
modelScene.rotation.x = -0.01 * Math.PI;
// modelScene.rotation.z = 0.03 * Math.PI;
this.scene.add(modelScene);
loading.dismiss();
this.render();
}
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.x = 1;
this.camera.position.y = 0.4;
this.camera.position.z = 16;
}
private createLight(){
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
this.scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 1, 1, 0 ).normalize();
this.scene.add( directionalLight );
}
private getAspectRatio(): number {
let height = this.canvas.clientHeight;
if (height === 0) {
return 0;
}
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
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.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.renderer.setClearColor(0xffffff, 1);
this.renderer.autoClear = true;
let component: MapComponent = 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.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(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.createCamera();
this.createLight();
this.startRendering();
this.addControls();
}
And map.html is
<canvas #canvas (mousedown)="onMouseDown($event)" (mouseup)="onMouseUp($event)"></canvas>
Use collision detection from three js utilities
Also use reference from this stack thread
https://stackoverflow.com/a/11480717/16768028

When I convert the collada from meshbasic to meshphong, parts of the collada disappear. Why is that?

When I convert the collada from meshbasic to meshphong, parts of the collada disappear. Why is that?
var setMaterial = function( node ) {
node.material = new THREE.MeshBasicMaterial({color: 0xff0000} );
console.log(node);
if (node.children) {
for (var i=0, thelength=node.children.length; i < thelength ; i++ ) {
setMaterial(node.children[i]);
}
}
}
setMaterial(dae);
This works, but then this makes half of it disappear...
var setMaterial = function( node ) {
node.material = new THREE.MeshBasicPhong({color: 0xff0000} );
console.log(node);
if (node.children) {
for (var i=0, thelength=node.children.length; i < thelength ; i++ ) {
setMaterial(node.children[i]);
}
}
}
setMaterial(dae);
i think there no material in the name THREE.MeshBasicPhong.....
change it as MeshPhongMaterial and have a try..
node.material = new THREE.MeshPhongMaterial({color: 0xff0000} );

Resources