three.js applying texture to stl mesh - javascript

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.

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?

Three.Js object file is loadded but material files are not loading

I created 1 small object file in the blender tool and then exported it to wavefront (.obj) format.
My code:
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'objs/' );
mtlLoader.load( 'final_blue_cup.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'objs/' );
objLoader.load( 'final_blue_cup.obj', function ( object ) {
scene.add( object );
}, onProgress, onError );
});
This is my output from my blender tool:
This is what is get after load in three.js:
With this link you can find my object, material and blender file: https://drive.google.com/drive/folders/1XW_teF6N3qqmqavsQrPpLZntJoMvqL0K
Can anyone help me in fixing it?

Display svg in three.js using WebGLRenderer

Can i show a svg in a three.js scene using the WebGL renderer? I know that this can be done using the SVG renderer and loader but I can't use it for my problem.
Thanks.
You can use the Sprite object and specify your svg file in the TextureLoader(), like so:
var map = new THREE.TextureLoader().load( "sprite.svg" );
var material = new THREE.SpriteMaterial( { map: map, color: 0xffffff, fog: true } );
var sprite = new THREE.Sprite( material );
scene.add( sprite );
You can read more here: Three.js - Sprite

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.

Categories

Resources