three.js how to make double sided object - three.js

Blender export obj don't export double sided objects. How can I render objects in double sided mode. I tried this without succes:
var loader = new THREE.OBJMTLLoader();
loader.load('models/test.obj');
loader.addEventListener( 'load', function ( event ) {
objects = event.content;
objects.position.set(0,5,0);
objects.scale.set(1.5,1.5,1.5);
objects.mesh.doubleSided = true;
scene.add(objects);
});

In your case, you add the following to your callback function:
objects.traverse( function( node ) {
if( node.material ) {
node.material.side = THREE.DoubleSide;
}
});
The doubleSided property of Mesh is deprecated. It was replaced with the side property of Material
Also, it is best to learn from three.js examples that work with the current version of the library.
three.js r.57

2022
Future readers! Just add the side option to the material constructor:
const material = new THREE.MeshLambertMaterial({
color: 0xff0000,
side: THREE.DoubleSide
// ^ this line here
});

Related

glb mesh disappears on rotation threejs

I've dug around looking for a solve for this - but couldn't find the answer on here. I have a gltf/glb model loading into three js as such:
createScene: function() {
this.renderer = new Three.WebGLRenderer({
antialias: true,
alpha: true
});
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setClearColor(new Three.Color('#fff'));
this.renderer.setClearAlpha( 0 );
//this.render.shadowMap.type = Three.PCFSoftShadowMap;
container.appendChild(this.renderer.domElement);
},
createCamera: function() {
this.camera = new Three.PerspectiveCamera(6, container.clientWidth/container.clientHeight, 1, 1000);
this.camera.position.set(0, 0, 40);
},
createShape: function() {
let me = this;
const loader = new GLTFLoader();
loader.load( 'model/fbf3.glb', function ( gltf ) {
me.bottle = gltf.scene
me.scene.add( gltf.scene );
gltf.scene.traverse(function(obj) { obj.frustumCulled = false; });
me.pivot = new Three.Group();
me.pivot.position.set( 0.0, 0.0, 0 );
me.bottle.add( me.pivot );
console.log(gltf.scene);
console.log(gltf.scene.children[1]);
//me.pivot.add( me.bottle );
me.animate();
}, undefined, function ( error ) {
console.error( error );
});
},
I found a post that said to loop through the scene and be sure to add frustumCulled to false - so that's added in ( and when I log the child, that objects frustumCulled is set to false ). In order to have a label on my object easy to map and also take on a different material/glossiness i've created another object in the group that is just slightly in front of my other object on the yaxis. When it is facing the camera, it works well - however, it is when the object rotates is where it disappears. Working:
Rotate enough, and gone:
Is there a setting in threejs that I need to add to be sure the render order is correct? Or is it something wrong with my object set up in Blender? Ideally I wouldn't have to UV wrap the whole bottle as one object and add the label to the bottle texture because I want the label to have less specularity ( that a word? ). Any help would be appreciated.
Solved - the tutorial is slightly old ( 2+years ) and now Blender ( the latest version 2.9+ ) has the Principled BSDF Shader baked in. Instead of using the glTF-Blender-Exporter-Master pbr appended shaders from the listed tutorial - I instead used the Principled BSDF Shader - linked my material to it's Base Color and linked that to the Material Output ( all in the node/now Shader Editor. No issues anymore.

GLTF model is too dark

Trying to load this model of a car into my scene, here is how it looks in the glTF Viewer:
I followed that example. With this updated loading method, the model is still dark, and if I try to scale or position it, it completely disappears.
Here is how it's loaded:
const loader = new THREE.GLTFLoader();
const roughnessMipmapper = new RoughnessMipmapper( renderer );
loader.load( 'models/car_datsun/scene.gltf', function ( gltf ) {
gltf.scene.traverse( function (child) {
if (child.isMesh) {
roughnessMipmapper.generateMipmaps(child.material);
}
child.scale.set(0.5,0.5,0.5); //must comment this line out to appear
child.position.y += 10; //must comment this line out to appear
child.position.z += 20; //must comment this line out to appear
});
scene.add(gltf.scene);
}, undefined, function ( error ) {
console.error(error);
});
roughnessMipmapper.dispose();
I also have a light, which is meant to simulate the sun:
const light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.set(500,200,500); //looking at 0,0,0
scene.add(light);
Renderer is set to use sRGB:
renderer.outputEncoding = THREE.sRGBEncoding;

How to replicate threejs.org/editor behavior for envMap in code with MTLLoader?

When creating a material in the editor at threejs.org/editor, there is a simple envMap field that allows you to upload a single image to be used as the environment map. I need to replicate this behavior in code using the MTLLoader. Here is my code:
var mtl_loader = new THREE.MTLLoader();
mtl_loader.setBaseUrl(model_base_url);
mtl_loader.setPath(model_base_url);
mtl_loader.load(model_mtl_name, function(materials) {
materials.preload();
var obj_loader = new THREE.OBJLoader();
obj_loader.setMaterials(materials);
obj_loader.setPath(model_base_url);
obj_loader.load(model_obj_name, function(object) {
scene.add( object );
render();
}, onProgress, onError);
});
But where do I include that environment map image? Obviously the editor is turning it into some THREE object.

How to add reflectionMaterial for an object in threejs

How to add reflectionMaterial with environment map, am using two cameras and two scene in order to achieve it, based on the webgl_materials_cubemap
and am using Object that is loaded using OBJMTLLoder, i can see the both Environment map, and Object on my scene, but the reflection of environment is not working on the object..
find my code below :
var urls = [
'textures/cube/canary/pos-x.png',
'textures/cube/canary/neg-x.png',
'textures/cube/canary/pos-y.png',
'textures/cube/canary/neg-y.png',
'textures/cube/canary/pos-z.png',
'textures/cube/canary/neg-z.png'
];
var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
cubemap.format = THREE.RGBFormat;
var shader = THREE.ShaderLib['cube']; // init cube shader from built-in lib
shader.uniforms['tCube'].value = cubemap; // apply textures to shader
// create shader material
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
});
skybox = new THREE.Mesh( new THREE.BoxGeometry( 1000, 1000, 1000 ), skyBoxMaterial );
scene.add( skybox );
var object = scene.getObjectByName ("myname", true);
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh )
{
//child.geometry.computeFaceNormals();
var geometry = child.geometry;
var reflectionMaterial = new THREE.MeshBasicMaterial({
color: 0xcccccc,
envMap: cubemap
});
mesh = new THREE.Mesh(geometry, reflectionMaterial);
sceneCube.add(mesh);
}
});
Here am just changing the scene.add(mesh); to sceneCube.add(mesh); the reflection worked but the camera doesn't ..
you can see the differences here
Example 1
Example 2
In the first demo you can see that the scene working fine with the environment and without Object reflection
In the second you can see that the Reflection working fine but the camera behavior gets wired
i fixed it myself by adding following line inside the Object traverse
child.material.map = reflectionMaterial;
child.material.needsUpdate = true;
However i don't know am doing is correct or not but it is worked as like expected,

threejs wireframe not working with OBJMTLLoader

am loading my object in threejs using OBJMTLLoader, the wireframe control is working alone for OBJLoader, but for the OBJMTLLoader it doesn't working
var loader = new THREE.OBJMTLLoader();
loader.load( 'obj/male02/male02.obj', 'obj/male02/male02_dds.mtl', function ( object ) {
object.children[0].geometry.computeFaceNormals();
var geometry = object.children[0].geometry;
console.log(geometry);
THREE.GeometryUtils.center(geometry);
geometry.dynamic = true;
var material = new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors });
mesh = new THREE.Mesh(geometry, material);
scene.add( mesh );
} );
function wireframe(){
//alert('hhhhhh');
mesh.material.wireframe = true;
mesh.material.color = new THREE.Color( 0x6893DE );
}
but it causing the following error, so my model is not showing on the viewer,
so here i want to know that we can create wireframe on any kind of 3d models??
object.children[0].geometry is undefined
Even though the OBJMTLLoader returns a THREE.Object3D object which does have .children, you should not assume that the .children is of type THREE.Mesh. So you should actually traverse() the THREE.Object3D in order to find the THREE.Mesh.
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh )
// do something with the geometry
} );

Resources