How can I make an OBJ + MTL loaded doublesided? - three.js

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

Related

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.

Simply assign a Material to loaded .OBJ - ThreeJS

I've been hitting myself overhead with this one for the good three hours now..
My question is, would someone be kind enough to reorganize my example in such a way, that the object that I load comes with a color, any color
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
}
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
If I throw the traverse part away the object is loaded successfully but is a simple white color, with it, the object does not appear on my screen...
<script src="../build/three.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/SMAAShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/SMAAPass.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
These are my imports in case you think the problem lies in here
Thanks so much in advance, this is a project which I'm developing independently and would love it if I can get it working!
I feel like an idiot but the thing I was missing was
);
at the end of object.traverse function
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
});
// ^This over here^
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
Assigning a material now works perfectly with this code.

How can I load a group of objects to a global variable with OBJLoader without type-error messages?

I'm using the following code to load OBJ objects, but in order to load the resulted group on a global variable, I pre-define the variable as 'null' which raises Type-error messages in Firefox console. I tried defining it as THREE.Group, THREE.Mesh, etc to no avail -those are causing the code to not execute.
How can I have the same functionality without those annoying error messages?
//this is causing Type-error messages in FF dev tools
var femModel = null;
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete,2)+ '% downloaded');//<<<<
}
if (percentComplete = 100){
waitmodeltoload();//<<<<<<
}
};
var onError = function ( xhr ) { };
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'female02/' );
mtlLoader.setMaterialOptions({ side:THREE.DoubleSide });
// the code in question:
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 ) {
femModel = object;
}, onProgress, onError );
});
var waitid;
function waitmodeltoload(){
if (!femModel){
clearTimeout(waitid);
waitid = setTimeout(setupmodel, 100);
}
setupmodel();//<<<<<
}
function setupmodel(){
var intersects=null;
femModel.traverse( function ( child ) { // <<<<<<<<
if ( child instanceof THREE.Mesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
} );
femModel.position.set( 0, -90, 0 );
sceneR2S.add( femModel );
}
OK, that was simpler than I thought, it was a logical error of mine, I overlooked that the code was trying to access femModel before it was available:
So instead of:
var waitid;
function waitmodeltoload(){
if (!femModel){
clearTimeout(waitid);
waitid = setTimeout(setupmodel, 100);
}
setupmodel();
}
It should be:
var waitid;
function waitmodeltoload(){
if (!femModel){
clearTimeout(waitid);
waitid = setTimeout(setupmodel, 100);
}else{
setupmodel();
}
}
In the first case setupmodel() was called even if the model wasn't loaded.
An "else" was all that was needed -no more red-alert Type-error messages.

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.Js How acess a object outside the OBJMTLLoader

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);

Resources