Reputation: 245
I have made an OBJ-file with blender. This file has two materials assigned. The file is being imported nicely.
But: How do I assign different materials to the faces in three.js? I understand, that the materials have to be inside of an array (no idea, if I did it right). And now, I want to assign the material to the faces.
This is the interesting part of my code:
....
loader.load( './beardedbox3.obj', addBananaInScene);
};
var addBananaInScene = function(object){
banana = object;
//Move the banana in the scene
banana.rotation.x = Math.PI/2;
banana.position.x = 0;
banana.position.y = 0;
banana.position.z = 0;
banana.scale.x = 200;
banana.scale.y = 200;
banana.scale.z = 200;
var weiss = new THREE.MeshPhongMaterial( { color: 0xffffff,
specular: 0xffffff,
shininess: 30,
shading: THREE.FlatShading } );
var rot = new THREE.MeshPhongMaterial( { color: 0xff0000,
specular: 0xFF9900,
shininess: 30,
shading: THREE.FlatShading } );
object.traverse( function ( child ) {
if(child instanceof THREE.Mesh){
child.materials = [weiss, rot];
child.geometry.computeVertexNormals();
}
});
//Add the 3D object in the scene
scene.add(banana);
The OBJ-file looks like this:
.... Some vertex-coordinates
usemtl weiss
s 1
f 1//1 2//1 3//1
f 4//2 5//2 6//2
... some more faces
f 130//23 34//23 141//23
usemtl rot
f 41//51 42//51 43//51
f 45//52 46//52 47//52
f 42//53 11//53
... even more faces
This seems to me, as if I could use a simple loop, which assigns the materials to faces. But I don't know, how to do that. Or is there an easier way?
Regards Christian
edit:
Thanks for your answer, Sounds logical to me, but unfortunately i didn't get it to work. I seem to be missing some basic knowledge.
Important part of my code now looks like this:
var weiss = new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0xffffff,
shininess: 30,
shading: THREE.FlatShading
});
var rot = new THREE.MeshPhongMaterial({
color: 0xff0000,
specular: 0xFF9900,
shininess: 30,
shading: THREE.FlatShading
});
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.materials = [weiss, rot];
child.geometry.computeVertexNormals();
child.geometry.elementsNeedUpdate = true;
for (var i = 0; i < child.geometry.faces.length; i++) {
if (i < child.geometry.faces.length / 2) {
child.geometry.faces[i].materialIndex = 0;
} else {
child.geometry.faces[i].materialIndex = 1;
}
}
}
});
And I get the errormessage:
TypeError: child.geometry.faces is undefined
addBananaInScene/<() box.js:78
THREE.Object3D.prototype.traverse() three.min.js:179
THREE.Object3D.prototype.traverse() three.min.js:179
addBananaInScene() box.js:69
THREE.OBJLoader.prototype.load/<() OBJLoader.js:25
THREE.XHRLoader.prototype.load/<() three.min.js:377
I guess, I did something very stupid ;)
Thanks in advance for your appreciated help.
Christian
Upvotes: 0
Views: 2229
Reputation: 81
You can load multiple material in single object. Use below code
var loader = new THREE.OBJLoader( manager );
loader.load( 'obj_model/Jersey_1.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
materials.push(new THREE.MeshLambertMaterial( { map : THREE.ImageUtils.loadTexture( 'obj_model/Jrsy_1_Color_1.png'),transparent: true, opacity: 1,color: 0xFF4C33 } ) );
materials.push(new THREE.MeshLambertMaterial( { map : THREE.ImageUtils.loadTexture( 'obj_model/Jrsy_1_Color_2.png'),transparent: true, opacity: 1,color: 0xFFF933 } ) );
materials.push(new THREE.MeshLambertMaterial( { map : THREE.ImageUtils.loadTexture( 'obj_model/Jrsy_1_Tag.png'),transparent: true, opacity: 1,color: 0xFF0000 } ) );
materials.push(new THREE.MeshLambertMaterial( { map : THREE.ImageUtils.loadTexture( 'obj_model/Jrsy_Ptrn.png'),transparent: true, opacity: 1,color: 0xFF33E0 } ) );
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.scale = new THREE.Vector3( 8,8,8 );
scene.add(mesh);
});
Upvotes: 1
Reputation: 2853
Yes. Use the multimaterial.
http://threejs.org/docs/#Reference/Materials/MultiMaterial
And then where, for example you have a material for each face and you have access to your geometry after the obj has loaded, you could have the first half of faces use one material and the remaining faces use another:
for ( var i = 0; i < geometry.faces.length; i ++ ) {
if(i<geometry.faces.length/2){
geometry.faces[i].materialIndex = 0;
}else{
geometry.faces[i].materialIndex = 1;
}
}
Upvotes: 2