How to applying THREE.EdgesGeometry in a object loaded with THREE.OBJLoader? - javascript

I try several times to implement the edges in a model loader with the OBJLoader but can't do it.
Mloader = new THREE.MTLLoader();
Mloader.setPath( dir );
Mloader.load( mtl_dir, function ( materials ) {
materials.preload();
OLoader = new THREE.OBJLoader();
OLoader.setMaterials( materials );
OLoader.setPath( dir );
OLoader.load( name_file, function ( object ) {
object.scale.set( scale, scale, scale );
scene.add( object );
var edges = new THREE.EdgesGeometry( object, 11 );
var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {color: 0x111111 } ) );
line.scale.set( scale, scale, scale );
scene.add( line )
} );
} );
The model load fine, but the edges don't.
When the model is loader with the STLloader the edges of the geometry render fine, but i need to do it with .obs files.
var loader = new THREE.STLLoader();
loader.load(dir, function (geometry) {
material = new THREE.MeshPhongMaterial({
color: 0xAAAAAA,
specular: 0x111111,
shininess: 200
});
var edges = new THREE.EdgesGeometry(geometry, 11);
var line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({color: 0x111111}));
line.scale.set(scale, scale, scale);
scene.add(line)
});
STL vs OBJ Loader

Thanks, yes it a group. The code with the solution:
Mloader = new THREE.MTLLoader();
Mloader.setPath( dir );
Mloader.load( mtl_dir, function ( materials ) {
materials.preload();
OLoader = new THREE.OBJLoader();
OLoader.setMaterials( materials );
OLoader.setPath( dir );
OLoader.load( name_file, function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.castShadow = true;
edges = new THREE.EdgesGeometry( child.geometry,11);
line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {
color: 0x111111
} ) );
line.scale.set( scale, scale, scale );
line.position.set( 0, 0.7, 0 );
scene.add( line );
}
} );
object.scale.set( scale, scale, scale );
object.position.set( 0, 0.7, 0 );
scene.add( object );
} );
} );

Related

Why model renders with a blade color with Three.js?

Hi, I imported my model (obj + mtl + texture) but it renders with a blade color.
Normally it should be like this :
Currently the code of the scene configuration is:
loadModel()
scene.current.background = new THREE.Color( 'transparent' );
scene.current.add(new THREE.AxesHelper( 5 ));
const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 100, 100 ), new THREE.MeshPhongMaterial( { color: 0xffffff, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.current.add( mesh );
controls.current.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.current.dampingFactor = 0.2;
controls.current.screenSpacePanning = false;
controls.current.maxPolarAngle = Math.PI / 2;
controls.current.maxDistance = 200
controls.current.minDistance = 20
controls.current.target = new THREE.Vector3(0, 16, 0)
camera.current.position.set( -3, 17, 8 );
camera.current.lookAt(new THREE.Vector3( 0, 15, 0 ));
controls.current.update();
scene.current.background = new THREE.Color( 0xFFFFFF );
const ambilentLight = new THREE.AmbientLight( 0xffffff, 0.5)
scene.current.add(ambilentLight)
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff );
hemiLight.position.set( 0, 500, 30 );
hemiLight.castShadow = true
scene.current.add( hemiLight );
scene.current.add(new THREE.HemisphereLightHelper( hemiLight, 5 ));
const dirLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
dirLight.position.set( -10, 50, 50 );
dirLight.castShadow = true;
scene.current.add( dirLight );
scene.current.add(new THREE.DirectionalLightHelper( dirLight, 5 ));
renderer.current.shadowMap.enabled = true;
renderer.current.setPixelRatio( window.devicePixelRatio );
renderer.current.setSize( window.innerWidth, window.innerHeight );
renderer.current.outputEncoding = THREE.sRGBEncoding;
renderer.current.toneMapping = THREE.ACESFilmicToneMapping;
renderer.current.toneMappingExposure = 1;
renderer.current.physicallyCorrectLights = true;
container.current.appendChild(renderer.current.domElement);
window.addEventListener( 'resize', onWindowResize );
animate();
I dont know if it's a problem of lighting or another thing.
Anybody know this problem ?
If you are working with OBJ/MTL and set WebGLRenderer.outputEncoding to THREE.sRGBEncoding;, I suspect the issue is caused by an incomplete color space configuration. You can solve this in two way:
Do no touch outputEncoding.
Set the encoding property of all color textures to THREE.sRGBEncoding;.
Since OBJLoader returns an instance of THREE.Group, you can update the textures like so:
group.traverse( function( object ) {
if ( object.isMesh === true && object.material.map !== null ) {
object.material.map.encoding = THREE.sRGBEncoding;
}
} );
BTW: You normally use tone mapping only if you apply HDR textures to your scene.

Use multiple Textures in export loader `obj` file in three.js

I tried to use different textures in export loader obj file.
I am able to make my object visible on the scene but I couldn't set either its size nor its shape.
Any idea on what is wrong/is missing in my code ?
var loader = new THREE.OBJLoader();
loader.load(
'models/Sofa/sofa.obj',
function (object) {
var geometry = object.children[ 0 ].geometry;
var materials = [];
materials.push(new THREE.MeshBasicMaterial( { map : THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/1.jpg')}));
materials.push(new THREE.MeshBasicMaterial( { map : THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/paradis_beige.jpg')}));
materials.push(new THREE.MeshBasicMaterial( { map : THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/2.jpg')}));
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = material;
}
});
scene1.add(mesh);
},
function ( xhr ) {
returnValue = ( xhr.loaded / xhr.total * 100 ) + '% loaded';
console.log(returnValue);
},
function ( error ) {
console.log( 'An error happened' );
}
);

ThreeJS, adding Subdivision Modifier to Objectloader-based scene

I'm attempting to user the Subdivision Modifier on an objectloader-loaded scene. I am getting the following javascript error when attempting this:
"BufferSubdivisionModifier.js:514 Uncaught TypeError: Cannot read property 'array' of undefined"
My code is the following to load the object with the subdivision modifier.
var loader = new THREE.ObjectLoader();
loader.load("../js/brain2.json", function(object) {
var material = new THREE.MeshPhongMaterial( { color: 0x888888, specular: 0x222222, shininess: 20} );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
var modifier = new THREE.BufferSubdivisionModifier( 1 );
child.material = material;
child.geometry.computeFaceNormals();
modifier.modify( child.geometry );
child.material.overdraw = 1
};
});
object.scale.set(15, 15, 15);
object.position.x = 1;
object.position.y = 1;
object.position.z = 1;
object.rotation.set( 1, 1, 1 );
scene.add( object );
});
If I had to guess, it's that the subdivision modifier dislikes the 'child.geometry' object?
Solution is to load geometries for the chilren.
var loader = new THREE.ObjectLoader();
loader.load("../js/brain2.json", function(object) {
var material = new THREE.MeshPhongMaterial( { color: 0x888888, specular: 0x222222, shininess: 20} );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
child.geometry = new THREE.BufferGeometry().fromGeometry( geometry );
var modifier = new THREE.BufferSubdivisionModifier(1);
modifier.modify(geometry);
child.material.overdraw = 1
};
});
object.scale.set(15, 15, 15);
object.position.x = 1;
object.position.y = 1;
object.position.z = 1;
object.rotation.set( 5, 1, 1 );
scene.add( object );
});

scene loaded via objectloader, bump map not rendering

attempting to apply a bump map to an object loaded, but no change is seen on the material
var loader = new THREE.ObjectLoader();
loader.load("../js/brain2.json", function(object) {
var mapHeight = new THREE.TextureLoader().load( "../js/texture.jpg" );
var material = new THREE.MeshPhongMaterial( { color: 0x888888, specular: 0xEEEEEE, shininess: 5} );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
child.material.bumpMap = mapHeight;
child.material.bumpScale = 1;
var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
child.geometry = new THREE.BufferGeometry().fromGeometry( geometry );
var modifier = new THREE.BufferSubdivisionModifier(1);
modifier.modify(geometry);
child.material.overdraw = 1
};
});
object.scale.set(15, 15, 15);
object.position.x = 1;
object.position.y = 1;
object.position.z = 1;
object.rotation.set( 5, 1, 1 );
scene.add( object );
});
I've already fixed earlier issues with this code, including applying a subdivision modifier to it, but now it appears the bump map refuses to be applied.

How to work with Geometry from AMFLoader in THREE.js?

I am using STLLoader and AMFLoader to load models in a scene. When the file is an STL file, I load the file and calculate the bounding box along with my own functions for calculating the volume and surface area:
var loader = new THREE.STLLoader();
loader.load('file.stl'', function ( geometry ) {
var material = new THREE.MeshLambertMaterial( { color: 0xeaeaea/*, specular: 0x111111, shininess: 100*/ } );
geometry.computeBoundingBox(geometry);
bBox = geometry.boundingBox;
geometry.computeVertexNormals();
// convert buffergeometry to geometry so attributes can be used to calculate volume and area
var calcGeometry = new THREE.Geometry().fromBufferGeometry(geometry);
// calculate Volume
modelVolume = calculateVolume(calcGeometry);
// calculate Surface Area
modelArea = calculateArea(calcGeometry);
meshMain = new THREE.Mesh( geometry, material );
meshMain.position.set( 0, 0, 0 );
meshMain.rotation.set( 0, - Math.PI / 2, 0 );
meshMain.scale.set( 1, 1, 1 );
// center the rotational pivot point on center of geometry
meshMain.translation = geometry.center();
// bounding box info
showBoundingBox = new THREE.BoxHelper(meshMain, bBoxColor);
meshMain.castShadow = true;
meshMain.receiveShadow = true;
scene.add( meshMain );
});
However, it seems that the AMFLoader returns the Mesh. How do I work with the geometry of the returned mesh? This is what I've tried:
var loader = new THREE.AMFLoader();
loader.load( 'file.amf', function ( amfobject ) {
console.log(amfobject.geometry); // undefined
scene.add( amfobject );
} );
EDIT
This is what I am attempting to do:
amfobject.children.forEach(function (child) {
child.geometry.computeFaceNormals();
child.geometry.computeVertexNormals();
child.geometry.computeBoundingBox();
});
but it says that child.geometry is undefined.

Categories

Resources