THREE.Js How acess a object outside the OBJMTLLoader - three.js

Does anybody knows how can i acess a object outside a OBJMTLLoader
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(0,0,0);
scene.add( object );
});
console.log(object);
inside of the function objects = THREE.Object3D but outside is equal do ObjectLoad.
Thanks for everybody.

The object is simply inside the scope of the undefined function.
Set the function to return the object
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(0,0,0);
return object;//here
});
scene.add( object );
console.log(object);

Related

How do i animate my 3D model to spin like a spinning coin in three.js?

been stuck for hours trying to figure out how to make my 3d model spin like a coin spinning. my code is below anything help i really appreciate you guys.
// add a light
const light = new THREE.AmbientLight(0xffffff,5)
scene.add(light);
// controls
// load object
const loader = new THREE.GLTFLoader();
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
const render = function() {
requestAnimationFrame(render)
// camera.rotation.z += .0010
renderer.render(scene, camera);
}
render();
Try it like so:
let myModel;
const loader = new GLTFLoader();
loader.load( 'model.gltf', function ( gltf ) {
myModel = gltf.scene;
scene.add( myModel );
} );
const render = function() {
requestAnimationFrame(render)
if ( myModel ) {
myModel.rotation.z += 0.01;
}
renderer.render(scene, camera);
}
The problem is, you are defining the model gltf inside a function, which means that it cannot be accessed from render(). In order to spin the model, you need to define the variable gltf prior to loading the model, so it can be stored inside of it:
const loader = new THREE.GLTFLoader();
var gltf; //By defining it prior to loading, it is now in global scope.
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
Then, you can add the flipping effect in the render() loop. Make sure that you add the given if statement so it doesn't crash before the model even loads!
const render = function() {
requestAnimationFrame(render);
if(gltf) {
gltf.rotation.z += .0010; //Make sure you rotate the gltf, not the camera.
}
renderer.render(scene, camera);
}
And that should do it!
Note: I've taken a look at some of the other answers, and it seems like they either don't work, or they don't explain what they are doing properly. I think that this should help you achieve what you want.

I can't load the model using GLTFLoader

this.loadMyModel = function(){
const loader2 = new THREE.GLTFLoader();
// Load a glTF resource
loader2.load(
// resource URL
'Duck.gltf',
// called when the resource is loaded
function ( gltf ) {
//alert('success');
this.scene.add( gltf.scene );
})
};
The js files have been included.
I got an error, but I don't know why:
TypeError:undefined is not an object (evaluating 'this,scene.add')
Inside of your callback function, this is not the same as outside of the function. For more information on how this works in JS, I'd suggest this article: http://www.digital-web.com/articles/scope_in_javascript/
To fix the issue, you should save a reference to the scene outside the callback:
var scene = this.scene;
this.loadMyModel = function () {
// ...
loader.load( 'foo.glb', function ( gltf ) {
scene.add( gltf.scene );
} );
}
Alternatively, using newer JS features like arrow functions will also get around this problem.

How can I make an OBJ + MTL loaded doublesided?

with the loader bellow the obj and mtl files are loaded, so how can I access the material and make it doublesided?
If I use mtlLoader.setMaterialOptions({side: THREE.DoubleSide}) as in the following threejs.org documentation page, it doesn't work -and I'm not getting any hinting from VScode about the .setMaterialOptions either.
https://threejs.org/docs/#examples/loaders/MTLLoader
Here's the main part of the obj+mtl loader:
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'female02/' );
//mtlloader.setMaterialOptions(side:THREE.DoubleSide)
mtlLoader.load( 'female02.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'female02/' );
objLoader.load( 'female02.obj', function ( object ) {
object.position.set( 0, -95, 0 );
sceneRTT.add( object );
}, onProgress, onError );
});
[and I can't add the main keyword "doublesided" because I lack... reputation]
In MTLLoader.setMaterialOptions( options ), the options argument is an object, so you must pass it as such.
loader.setMaterialOptions( { side: THREE.DoubleSide } );
three.js r.89

raycast : Cannot read property 'visible' of undefined

i'm trying to load my .obj & MTL file into threejs and apply simple wall collision using raycaster. The scene has walls and other objects.
Used pointer control example
the loading and texturing are in place
problem is when using raycaster it throws an error "cannot read property visible of undefined" I guess my referencing is bad.
i used scene.children for passing objects in raycaster
here is the code for ray caster and obj loader. please let me know where im going wrong
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( 'neavik/' );
mtlLoader.setPath( 'neavik/' );
mtlLoader.load( 'room.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'neavik/' );
objLoader.load( 'room.obj', function ( object ) {
object.position.y = - 5;
object.scale.x=object.scale.y=object.scale.z=0.05
object.traverse( function( child ) { if ( child instanceof THREE.Mesh ) {
if (child.material.name == "Interior_wall") {
child.material = innerwall;
child.castShadow = true;
child.receiveShadow = true;
}
if (child.material.name == "Loby") {
child.material = innerwall1;
child.castShadow = true;
child.receiveShadow = true;
}
if (child.material.name == "TV_Black_Plastic") {
child.material = Black;
child.castShadow = true;
child.receiveShadow = true;
}});
object.name = "object";
scene.add( object );
});
} );
//Raycast
var rayCaster = new THREE.Raycaster(controls.getObject().position, cameraDirection);
var intersects = rayCaster.intersectObject(scene.children, true); //getting error on this line
$("#status").html("camera direction x: " + cameraDirection.x + " , z: " + cameraDirection.z);
// rest of the code
I had the same error and in my case the reason was that the object to be intersected was not existing yet or found at time of intersection.
Therefore I added a kind of null check to prevent this error message:
if (typeof scene != "undefined")

THREE.OBJMTLLoader progress listener

Am I able to add progress event listener to THREE.OBJMTLLoader?
I've tried this but it didn't work...
var callbackProgress = function( progress, result ) {}
var loader = new THREE.OBJMTLLoader();
loader.callbackProgress = callbackProgress;
loader.load(...);
Unless the signature has changed this should work :
loader = new THREE.OBJMTLLoader();
loader.load
(
'thefile.obj',
'thefile.mtl',
function ( object )
{
// onload ...
scene.add( object );
animate();
},
function ( progress, result )
{
console.log (100 * progress.loaded / progress.total);
}
);

Resources