adding external texture to three.js scene object - javascript

just getting my hands dirty with three.js and im curious on something that may be relatively simpleā€¦
I built a scene in the three.js editor and have figured out how to load the scene. In the editor, I added an image as a map texture but I realize it wont know where it is loaded externally on my server. So I've loaded the scene and objects and lights, but how can I map my textures to the objects?
// MATERIALS
var wireframe = THREE.ImageUtils.loadTexture( 'textures/wireframe.jpg' );
wireframe.wrapS = wireframe.wrapT = THREE.RepeatWrapping;
wireframe.repeat.set( 4, 4 );
var wireframeMaterial = new THREE.MeshLambertMaterial({
map : wireframe,
side : THREE.DoubleSide
});
// LOAD SCENE
var loader = new THREE.ObjectLoader();
loader.load( 'js/scene.js', function ( obj ) {
obj.traverse( function( node ) {
if ( node instanceof THREE.Mesh ) {
node.castShadow = true;
node.receiveShadow = true;
var plane = scene.getObjectByName( "plane", true );
plane.material = wireframeMaterial;
}
});
scene.add( obj );
render();
});
When adding plane.material = wireframeMaterial; into the loader, all my objects just disappearā€¦ How can I properly map the wireframeMaterial the plane object?
working example with var plane and plane.material commented out:
http://goo.gl/czSg7P
Scene:
http://goo.gl/BAVgVS

To map the texture you have to create a material using your texture and apply it to your plane.
If necessary you can set repetition of your texture with:
wireframe.wrapS = THREE.RepeatWrapping;
wireframe.wrapT = THREE.RepeatWrapping;
wireframe.repeat.set( 4, 4 );
And then you need to do something like this:
material = new THREE.MeshLambertMaterial({ map : wireframe, side : THREE.DoubleSide });
plane.material = material;
EDIT
You create a scene inside a scene. Since the loader returns a scene and then you add it again to a scene. This will give issues for sure.
Try to replace scene.add( obj ); with this in your loader:
for( var i = 0; i < obj.children.length; i++ ){
scene.add( obj.children[i] );
}
Not sure if that causes the problem, but I made a fiddle and it all seems to work fine for me. The problem is that I can't load external sources in my fiddle so instead I had to use your image as base64 string and the code becomes a bit different.
This means you have to change it a bit to make it work again with an image from your local folder.
If you exchange the Whole //TEXTURE part of the code with the following it should work:
var texture = new THREE.ImageUtils.loadTexture( 'img/wireframe.jpg' );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 1, 1 );
var textureMaterial = new THREE.MeshLambertMaterial({ map: texture, side : THREE.DoubleSide });

Related

Threejs: How to export an imported obj with Draco compressor

I only have limited javascript skills, i can get basic things working in threejs. Now I am struggeling with the draco exporter.
# Threejs.org there is an example of the Draco exporter
This example uses a generated mesh and is working perfectly:
// export mesh
var geometry = new THREE.TorusKnotBufferGeometry( 50, 15, 200, 30 );
var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
mesh = new THREE.Mesh( geometry, material );
mesh.castShadow = true;
mesh.position.y = 25;
scene.add( mesh );
I can import the .obj and this also works fine
new OBJLoader()
.setPath( '../models/mymodel/' )
.load( 'mymodel.obj', function ( mesh ) {
mesh.traverse( function ( child ) {
if(child.name=='mymodel_part1'){
child.material = Material1;
}
if(child.name=='mymodel_part2'){
child.material = Material2;
}
if(child.name=='mymodel_part3'){
child.material = Material3;
}
} );
scene.add( mesh );
} );
Now I want to export the mesh, and this does not work, I get a "TypeError: mesh is undefined".
So the Type is not correct, but what should it be, and how do I change it?
The problem is that OBJLoader.load() does not produce a group but an instance of THREE.Group. Hence, you have to first determine the correct mesh in the group's descendants. This however depends on the asset since OBJ files can contain multiple mesh definitions. I've prepared a live example that demonstrates this workflow. The important code section is:
var loader = new OBJLoader();
loader.load( 'https://threejs.org/examples/models/obj/tree.obj', function ( obj ) {
scene.add( obj );
mesh = obj.children[ 0 ];
} );
https://jsfiddle.net/bquxjf28/2/

Three.js transparency model texture bug

I have searched over all internet and tried a lot of ways, but no results..
How to remove texture transparency bug? Check on image
So, on 3dsmax model looks okey. I have converted to .js format from .obj with python script in order .png files were transparent (.obj does not make transparence).
How to solve my problem? Thank you
var loader = new THREE.JSONLoader();
loader.load('tree_model.js', function(geometry, materials) {
var material = new THREE.MeshFaceMaterial(materials);
var object = new THREE.Mesh(geometry, material);
object.traverse( function ( child ) {
if ( child.material instanceof THREE.MeshPhongMaterial ) {
// this code is unattainable, but anyway without if (..) it does not work
child.material.alphaTest = 0.5;
child.material.depthWrite = false;
child.material.depthTest = false;
child.material.side = THREE.BackSide;
child.material.transparent = true;
}
});
scene.add(object);
});
});
And renderer:
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, premultipliedAlpha: true });
You have to set alphaTest on your materials. Additionally setting the leafes and branches to THREE.DoubleSide ensures that they are not disappearing when viewed from the other side.
The code you have posted contains various errors, so replace it with this:
var loader = new THREE.JSONLoader();
loader.load('model/Elka.js', function(geometry, materials) {
for( var i = 0; i < materials.length; i ++ ) {
var material = materials[ i ];
material.alphaTest = 0.5;
material.side = THREE.DoubleSide;
// not-so-good practice
if ( material.name === "NorwaySpruceBark" ) {
material.transparent = false;
}
}
var material = new THREE.MeshFaceMaterial(materials);
var object = new THREE.Mesh(geometry, material);
scene.add(object);
});
To further reduce transparency artefacts, set the trunk to non-transparent. Your model should contain the correct material settings, so this is kind of a bad practice.
Edit: Setting alpha and premultipliedAlpha in the renderer is not necessary for this problem.
Result:

Three.js: viewangle affects texture strength

My mesh has a baked shadow texture.
Unfortunately I got a weird result If I move the camera to a steeper viewangle.
What can I do to prevent this ?
loader.load( "mesh.js", function(geometry){
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( {
map: THREE.ImageUtils.loadTexture( "texture.png" ),
}));
scene.add(mesh);
});
Look at the example: http://threejs.org/examples/#webgl_materials_texture_anisotropy
Use:
var maxAnisotropy = renderer.getMaxAnisotropy();
texture.anisotropy = maxAnisotropy;
If you would like to learn more, you can look up Anisotropic Filtering.

Threejs TextureLoader CubeGeometry

I am learning threejs and I want that my cube has 6 different textures on each side. I did make that with loadTexture
var material3 = new THREE.MeshPhongMaterial( {map: THREE.ImageUtils.loadTexture('textures/ps.png')} );
I did save 6 of this materials in array and then use THREE.MeshFaceMaterial. But there is problem with THREE.ImageUtils.loadTexture because it is deprecated and I should use THREE.TextureLoader and I do not know how to load 6 textures in this way.
This is what I have:
function texture()
{
var loader = new THREE.TextureLoader();
loader.load( 'textures/ps.png', function ( texture )
{
var geometry = new THREE.CubeGeometry( 10, 10, 10 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
mesh = new THREE.Mesh( geometry, material );
mesh.position.z = -50;
scene.add( mesh );
} );
}
I think this is close to what you are looking for:
function MultiLoader(TexturesToLoad, LastCall, ReturnObjects) {
if (TexturesToLoad.length == 0) return;
if (!ReturnObjects) ReturnObjects = [];
var loader = new THREE.TextureLoader()
//Pop off the latest in the ,
//you could use shift instead if you want to read the array from
var texture = TexturesToLoad.shift()
loader.load(texture,
function (texture) {
ReturnObjects.push(texture);
if (TexturesToLoad.length > 0) {
MultiLoader(TexturesToLoad, LastCall, ReturnObjects)
} else {
LastCall(ReturnObjects)
}
},
LoadProgress,
LoadError);
}
function LoadProgress(xhr) {
console.log(('Lodaing ' + xhr.loaded / xhr.total * 100) + '% loaded ');
}
function LoadError(xhr) {
console.log('An error happened ');
}
call it with this
var TexturesToLoad = []
TexturesToLoad.push("../surfacemap.jpg")
TexturesToLoad.push("../normalmap.jpg");
TexturesToLoad.push("../spekularmap.jpg");
var ReturnedMaterials=[];
var ReturnMaterials=[];
var LastCall=function(ReturnedMaterials)
{
var surfaceMap = ReturnedMaterials[0];
var normalMap = ReturnedMaterials[1];
var specularMap = ReturnedMaterials[2];
var decalMaterial = new THREE.MeshPhongMaterial(
{
map: surfaceMap,
normalMap: normalMap,
normalScale: new THREE.Vector2( 1, 1 ),
specularMap: specularMap,
transparent:false,
wireframe: false
} );
var globeGeometry = new THREE.SphereGeometry(100.0, SPHERE_SIDES, SPHERE_SIDES);
mesh = new THREE.Mesh( globeGeometry, decalMaterial );
mesh.rotation.x=Math.PI/2;
};
MultiLoader(TexturesToLoad,LastCall,ReturnMaterials)
Explanation:
The new THREE.TextureLoader, uses a callback function. This ensures that the ressource you are using is really loaded when you need to add it.
Callbacks are difficult however if you want to use a lot of material.
above MultiLoader allows you to call recursivly and then call back to the function you want to use all your materials at. The materials are collected into an array (ReturnObjects) .
There are many ways to achieve it. I'll show you 2;
1)
Make your object (cube) using own vertices and faces
.vertices.push( new THREE.Vector3( x, y, z ) );
.faces.push( new THREE.Face3( x, y, z ) );
I've prepared an example in jsfiddle.
2)
Using UV map. So first you need to prepare object with UV map in 3D software like Blender and export it as a JSON file.
I've also prepared an example in jsfiddle.
If you are not familiar with UV map or Blender, check toturials.

three.js load object/model and then manipulate sub-parts/children

I have a 3D model of a robot arm, that I want displayed and manipulated in the browser.
My question is: how do I load the model into three.js, so that I can manipulate all sub-parts of the robot arm.
As an example I have a rotary motor and a shaft attached as an assembly in Inventor.
Image: http://i.stack.imgur.com/custz.png
This is exported as an stl file and imported in Three.js using STLLoader.js.
Image: http://i.stack.imgur.com/nLmBe.png
I want to know how I can manipulate the shaft to turn to a specified angle.
I have loaded the model using the following code:
<div id="container"></div>
<script src="three.js\build\three.min.js"></script>
<script src="js\STLLoader.js"></script>
<script>
// Set size variables
var SIZE_x = 400, SIZE_y = 400;
// Set three main THREE variables
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, SIZE_x/SIZE_y, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
// Set renderer options
renderer.setSize(SIZE_x, SIZE_y);
renderer.setClearColor(0xEEEEEE, 1.0);
renderer.clear();
// Append to HTML Dom
//document.body.appendChild(renderer.domElement);
$('#container').append(renderer.domElement);
// Create light
var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight);
// Move camera
camera.position.x = 0;
camera.position.y = 20;
camera.position.z = 20;
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
mesh.traverse(function ( child ) {
//if ( child instanceof THREE.Mesh ) {
console.log("Hej: " + child);
//}
});
//scene.add( new THREE.Mesh( geometry ) );
console.log('Loaded');
} );
loader.load( 'models/AssemblySimple1.stl' );
// Render loop
var render = function () {
requestAnimationFrame(render);
camera.lookAt(scene.position);
renderer.render(scene, camera);
};
render();
</script>
Any points and hints are welcome. Also if there is a preferred export file format. I have both SolidWorks and Inventor at my disposal. Or if I've taken a completely wrong approach to the problem, please let me know of other ways.
Thanks
Three js has function called THREE.STLLoader() .This one can be used to load stl file.
Here is the way how it is loaded
var loader = new THREE.STLLoader();
var group = new THREE.Object3D();
loader.load("../lib/SolidFz.stl", function (geometry) {
console.log(geometry);
var mat = new THREE.MeshLambertMaterial({color: 0x7777ff});
group = new THREE.Mesh(geometry, mat);
group.rotation.x = -0.5 * Math.PI;
group.scale.set(0.6, 0.6, 0.6);
scene.add(group);
});
Here scene
var scene new THREE.Scene();
After that you have a created 3d object and loaded one added into that 3d object.Then you can control that 3d object as you wish. According to this way you can load several parts and do the what you want to do with that

Categories

Resources