JSONLoader and textures R61 - javascript

I recently updated to version r61 from r58 and have found that with JSONLoader even if i only want to return geometry I am still getting a 404 on a texture call from a shader in my model.js file.
loadModel: function( label, domobject, callback ) {
var model_path = '/models/js/' + label + '.js';
var texture_place = '/textures/' + label + '.jpg';
var loader = new THREE.JSONLoader()
function onLoad(event) {
domobject.append( Set.renderer.domElement );
}
var texture = new THREE.ImageUtils.loadTexture( texture_place, null, onLoad );
loader.load( model_path, function ( geometry ) {
var material = new THREE.MeshLambertMaterial({map: texture});
Set.asset = new THREE.Mesh( geometry, material );
Set.asset.position.x = Set.asset.position.y = Set.asset.position.z = 0;
Set.asset.scale.x = Set.asset.scale.y = Set.asset.scale.z = 1;
if ( callback ) callback();
});
},
I am setup this way as to prevent models from loading up black and then having the texture pop on, which is working great. The behavior I expected with JSONLoader was that
loader.load(model_path, function (geometry, materials) would dig into the model file and look for materials and textures and that just specifying 'geometry' would ignore shader / texture.
Furthermore,
Is there a more simple way to use JSONLoader it's texturePath argument and an onLoad function to ensure that my geo doesn't get rendered before a texture is finished loading ?
Thanks!

Related

How to add a material (.mtl) to an object (.obj) using three.js?

I have successfully gotten a .obj file to display using three.js from a snippet of code I found online which I adapted for my needs. But am now trying to add the .mtl material file and am getting stuck.
I've tried a few things but nothing seems to be working. I am new to three.js so am definitely misunderstanding something here...
Here is the current code I am using that works beautifully to display my .obj file:
var renderer, scene, camera, Nefertiti;
var ww = window.innerWidth,
wh = window.innerHeight;
function init(){
renderer = new THREE.WebGLRenderer({canvas : document.getElementById('scene')});
renderer.setSize(ww,wh);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50,ww/wh, 0.1, 10000 );
camera.position.set(0,0,500);
scene.add(camera);
//Add a light in the scene
directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 0, 0, 350 );
directionalLight.lookAt(new THREE.Vector3(0,0,0));
scene.add( directionalLight );
//Load the obj file
loadOBJ();
}
var loadOBJ = function(){
//Manager from ThreeJs to track a loader and its status
var manager = new THREE.LoadingManager();
//Loader for Obj from Three.js
var loader = new THREE.OBJLoader( manager );
//Launch loading of the obj file, addNefertitiInScene is the callback when it's ready
loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);
};
var addNefertitiInScene = function(object){
Nefertiti = object;
//Move the Nefertiti in the scene
Nefertiti.scale.set(0.7,0.7,0.7);
Nefertiti.rotation.x = 0.5;
Nefertiti.rotation.y = 5.5;
Nefertiti.rotation.z = 0.2;
Nefertiti.position.y = -40;
Nefertiti.position.z = 1;
//Go through all children of the loaded object and search for a Mesh
object.traverse( function ( child ) {
//This allow us to check if the children is an instance of the Mesh constructor
if(child instanceof THREE.Mesh){
child.material.color = new THREE.Color(0XFFFFFF);
//Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
child.geometry.computeVertexNormals();
}
});
//Add the 3D object in the scene
scene.add(Nefertiti);
var canvas = renderer.domElement;
canvas.addEventListener('mousemove', onMouseMove);
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
function onMouseMove(event) {
Nefertiti.rotation.y += event.movementX * 0.001;
Nefertiti.rotation.x += event.movementY * 0.0005;
}
};
init();
Here is a snippet I tried adding in to load the mtl file that didn't work (i've just shortened the actual path to /mypath/ for cleanliness here)
var loadOBJ = function(){
    var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/mypath/' );
mtlLoader.setPath( '/mypath/' );
var url = "/mypath/Nefertiti-3d.mtl";
mtlLoader.load( url, function( materials ) {
    materials.preload();
    //Manager from ThreeJs to track a loader and its status
    var manager = new THREE.LoadingManager();
    //Loader for Obj from Three.js
    var loader = new THREE.OBJLoader( manager );
    loader.setMaterials( materials );
    loader.setPath( '/mypath/' );
    //Launch loading of the obj file, addNefertitiInScene is the callback when it's ready 
    loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);
    object.position.y = - 95;
        scene.add( object );
    }, onProgress, onError );
};
From researching I can see that there must be a mesh for a material to work, but I just cant figure out from any documentation how I can correctly implement it.
Any assistance in being able to add a mtl file to my code would be so appreciated!!
** EDIT **
So I have changed the snippet of code based on the advice from Mugen87 to the below:
var loadOBJ = function(){
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( '/mypath/' );
var url = "/mypath/Nefertiti-3d.mtl";
mtlLoader.load( url, function( materials ) {
materials.preload();
//Manager from ThreeJs to track a loader and its status
var manager = new THREE.LoadingManager();
//Loader for Obj from Three.js
var loader = new THREE.OBJLoader( manager );
loader.setMaterials( materials );
loader.setPath( '/mypath/' );
//Launch loading of the obj file, addNefertitiInScene is the callback when it's ready
loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);
}, onProgress, onError );
};
And I have also included the MTLLoader.js from the examples on three.js (I'm not sure if this is right, I'm finding it difficult to find information on this) and am getting the below errors in console:
Uncaught SyntaxError: Cannot use import statement outside a module
(index):136 Uncaught TypeError: THREE.MTLLoader is not a constructor
at loadOBJ ((index):136)
at init ((index):132)
at (index):199
loadOBJ # (index):136
init # (index):132
(anonymous) # (index):199
Any ideas? Is there something wrong with how I have the MTL in the code?
object.position.y = - 95;
scene.add( object );
I suppose you have copied over both lines of code from the official OBJ/MTL example, right? Unfortunately, they don't make sense here since object is undefined. Keep in mind that addNefertitiInScene is your onLoad() callback which is responsible for adding the loaded object to the scene.
Besides, mtlLoader.setBaseUrl( '/mypath/' ); should not be necessary. The method was removed quite a while ago.
Also ensure with the browser's dev tools that the MTL file is actually loaded.
three.js R109

Three.JS - apply image textute to .OBJ

I'm trying to add an image texture to an loaded .OBJ
now it looks like that
https://cuplate.com/ttt.php
I use MeshBasicMaterial to load my image as a texture. I used that for different geometry on ThreeJS
OBJ loader is like this
var loader = new THREE.OBJLoader();
loader.load( './test1.obj',function ( object ) {
object.traverse( function ( node ) {
if ( node.isMesh) {
node.material = materialOuter;
}
});
scene.add( object );
});
the image doesnt show....
How should I place my image on the front side of this plate?

Add background to THREE scene

I am trying to add a background to a THREE scene, but I cannot get it to work. I followed the advice given here and here without success.
Here are the lines I added to my (complex) code:
// Load the background texture
var loader = new THREE.TextureLoader();
var texture = loader.load( 'textures/stars_texture2956.jpg' );
var backgroundMesh = new THREE.Mesh(
new THREE.PlaneGeometry(2, 2, 0),
new THREE.MeshBasicMaterial({
map: texture
}));
backgroundMesh.material.depthTest = false;
backgroundMesh.material.depthWrite = false;
// Create your background scene
backgroundScene = new THREE.Scene();
backgroundCamera = new THREE.Camera();
backgroundScene.add(backgroundCamera );
backgroundScene.add(backgroundMesh );
and the render function looks like this:
function render() {
renderer.render(backgroundScene, backgroundCamera);
renderer.render( scene, camera );
}
Still I do not see the background (it is still white), but everything else works as expected. Is there a way to fix this?
If you wish to add a static background to your scene then the easiest way is to make the background of your scene transparent and place an image under canvas:
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor( 0xffffff, 0);
If you wish to create panoramic background which changes when you rotate camera then you need to create a skybox - a big mesh around your scene textured with a set of textures which cover 360 degrees of view. Have a look at this example:
http://threejs.org/examples/#webgl_materials_envmaps
The map is undefined because the TextureLoader Constructor expects a manager, not an url.
// instantiate a loader
var loader = new THREE.TextureLoader();
// load a resource
var texture = loader.load( 'textures/land_ocean_ice_cloud_2048.jpg' );
http://threejs.org/docs/#Reference/Loaders/TextureLoader
To solve your problem with the two scenes, you need to disable autoClear. The second renderer call clears the first one. Set after initializing: renderer.autoClear = false;. Now manually clear in your render-function:
function render() {
renderer.clear(); // <-
renderer.render(backgroundScene, backgroundCamera);
renderer.render( scene, camera );
}
try to coding like this
THREE.ImageUtils.crossOrigin = '';
var img = 'http://bpic.588ku.com/back_pic/03/92/40/4957e29f80d8a4a.jpg!ww650';
var grass = THREE.ImageUtils.loadTexture(img);
new THREE.MeshLambertMaterial({ map: grass });
it works for me
I have found a solution: Instead of creating a different scene and not knowing how to add cameras/whatever so it get rendered correctly, just add the background mesh to the actual scene.
The code then is as follows:
// Load the background texture
var loader = new THREE.TextureLoader();
var texture = loader.load( 'textures/messier-41.jpg' );
var backgroundMesh = new THREE.Mesh(
new THREE.PlaneGeometry(2048, 2048,8,8),
new THREE.MeshBasicMaterial({
map: texture
}));
backgroundMesh.material.depthTest = false;
backgroundMesh.material.depthWrite = false;
which must be put before the code that adds the other parts of the scene.

Three js Progress loading OBJMTLLoader

I am wanting a method to get the loading progress of .obj and .mtl file in three.js.
In previous version (as r53) I do that with:
loader = new THREE.OBJMTLLoader();
loader.addEventListener('progress', function ( item ){
console.log( item.loaded, item.total, item );
});
but now, using version r67 I can´t do that whith this code.
I try with:
var loader = new THREE.OBJMTLLoader();
loader.load( 'obj/inicial/modelo.obj', 'obj/inicial/modelo.mtl', function(object){
scene.add( object );
}, function(item){
console.log(item);
});
but it doesn´t works.
I searched google but have not found anything about. Can someone help me?
Thans in advance.
Both LoadingManager and onProgress callbacks should/will be available in dev and in master soon, hopefully.
For onProgress, onError in OBJMTLLoader
https://github.com/mrdoob/three.js/pull/5423
For LoadingManager support
https://github.com/mrdoob/three.js/pull/5463
The OBJMTLLoader class is deprecated, instead the latest three.js (r78) uses MTLLoader plus OBJLoader, codes are something like below:
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'obj/male02/' );
mtlLoader.load( 'male02_dds.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'obj/male02/' );
objLoader.load( 'male02.obj', function ( object ) {
object.position.y = - 95;
scene.add( object );
}, onProgress, onError );
});

three.js applying texture to stl mesh

I am loading a STL exported from Rhino. All works ok, however, when I try and apply a simple texture to the mesh, the STL objects are not rendered at all.
What am I missing
Code is as follows:
var diamondTexture = THREE.ImageUtils.loadTexture('images/diamond.jpg');
...
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
stones = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial({color:0x99CC3B, ambient:0x99CC3B, map:diamondTexture}) );
scene.add( stones );
} );
loader.load( 'models/jwl0020-stones.stl' );
You could try geometry.computeTangents(). Once I added that my stl files were able to have a texture though... the texture does not not properly "fit" the model since there are no UVs.

Categories

Resources