I want to create my own mesh (THREE.js, using CanvasRenderer) by defining the geometry as a set of vertices and faces:
geometry = new THREE.Geometry();
...
geometry.vertices.push(new THREE.Vector3(0, 0, 0));
geometry.vertices.push(new THREE.Vector3(1, 0, 0));
geometry.vertices.push(new THREE.Vector3(2, 0, 0));
...
...
geometry.faces.push(new THREE.Face3(1, 4, 3));
geometry.faces.push(new THREE.Face3(1, 2, 4));
geometry.faces.push(new THREE.Face3(3, 4, 5));
...
geometry.computeFaceNormals();
Because I want my mesh to have different color faces, I generate an array of materials. As I have read in some tutorials, I call this array geometry.materials:
geometry.materials = [
new THREE.MeshBasicMaterial({ color: 0xFF00A0 }),
new THREE.MeshBasicMaterial({ color: 0x00FF00 }),
new THREE.MeshBasicMaterial({ color: 0x0000FF }),
...
];
And then, I assign the indices to geometry.faces[i].materialIndex:
geometry.faces[0].materialIndex = 0;
geometry.faces[1].materialIndex = 2;
geometry.faces[2].materialIndex = 1;
...
Finally, I generate the mesh and add it to the scene:
mesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial());
scene.add(mesh);
Well, this code is not working. All I get is an invisible mesh (no faces can be seen). My questions are:
Is 'geometry.materials' the default variable name to define material arrays? Which array are the values in faces[i].materialIndex referring to?
Why is my code not working?
Tutorials are almost always out-of-date. Study the three.js examples instead.
If you are using tutorials, be sure to also check the Migration wiki: https://github.com/mrdoob/three.js/wiki/Migration.
Geometry no longer has a materials property.
Instead of adding the materials array to geometry, do this:
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
three.js r.53
Related
I would like to draw a plane in ThreeJS with a point (e. g. 0, 10, 20) and a normal vector for the plane orientation. I simply just do no get the position or the orientation right. Please help me out. Regards
Here are two ways I've tried (with PlaneHelper):
const plane = new THREE.Plane(new THREE.Vector3(10, 10, 10), 3)
// does not work: planeObj.translate(new THREE.Vector3(100, 100, 100))
const helper = new THREE.PlaneHelper(plane, 50, 0x00ffff);
this.scene.add( helper )
Or without the PlaneHelper:
const geometry = new THREE.PlaneGeometry( 50, 50, 32 );
geometry.translate(100, 0, 0)
const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( geometry, material );
scene.add( plane );
// normal orientation missing
I'm attempting to create a sphere in three.js with a base material and a transparent png material over the top. I found this answer helpful in understanding how to load multiple materials. However when I try to apply this to SphereGeometry rather than BoxGeometry as in the example, only the second material is visible, with no transparency.
http://jsfiddle.net/oyamg8n3/1/
// geometry
var geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
geometry.addGroup( 0, Infinity, 2 );
geometry.addGroup( 0, Infinity, 3 );
// textures
var loader = new THREE.TextureLoader();
var splodge = loader.load( 'https://threejs.org/examples/textures/decal/decal-diffuse.png', render );
var cat = loader.load('https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80.jpeg', render)
// materials
var catMat = new THREE.MeshPhongMaterial( {
map: cat,
} );
var splodgeMat = new THREE.MeshPhongMaterial( {
map: splodge,
alphaTest: 0.5,
} );
var materials = [ catMat, splodgeMat ];
// mesh
mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
Can I use these same principles for
var geometry = new THREE.SphereGeometry( 5, 20, 20 );
It does work if you use SphereBufferGeometry and not SphereGeometry. Notice that both classes have a different super class. You want to work with the BufferGeometry version.
Demo: http://jsfiddle.net/r6j8otz9/
three R105
Does Three.js support Multi-tile UV?
I have a mesh with 2 sets of uvs exported from maya as .json file. I tried using MultiMaterial by defining 2 different material with 2 different set of textures like so:
var material1 = new THREE.MeshPhongMaterial({//side
color: 0xffffff,
map: textureLoader.load(topINF_TopSide_Side_DiffMap),
normalMap: textureLoader.load(topINF_TopSide_Side_NormalMap),
normalScale: new THREE.Vector3(1, 1),
displacementMap: textureLoader.load(topINF_TopSide_Side_DisplacementMap),
aoMap: textureLoader.load(topINF_TopSide_Side_AOMap),
specularMap: textureLoader.load(topINF_TopSide_Side_SMap),
});
var material2 = new THREE.MeshPhongMaterial({//top
color: 0xffffff,
map: textureLoader.load(topINF_TopSide_Top_DiffMap),
normalMap: textureLoader.load(topINF_TopSide_Top_NormalMap),
normalScale: new THREE.Vector3(1, 1),
displacementMap: textureLoader.load(topINF_TopSide_Top_DisplacementMap),
aoMap: textureLoader.load(topINF_TopSide_Top_AOMap),
specularMap: textureLoader.load(topINF_TopSide_Top_SMap),
});
materials.push(material1);
materials.push(material2);
then I created my mesh as follows
var mesh = new THREE.SceneUtils.createMultiMaterialObject( geometry, [material2, material1]);
mesh.children[0].material.transparent = true;
mesh.children[0].material.opacity = 0.5;
However it seems that it uses only the first set of uvs on the mesh since the textures appear on top of each others.
Here is the results I get in maya which I was hoping for
maya results
And here is what I get from Three.js
Threejs results
I'm trying to apply different material on front and back sides of extruded shape, but cannot figure out where to put side: THREE.FrontSide and side: THREE.BackSide. Where they should be putted?
My relevant code part is:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture });
var materialSide = new THREE.MeshPhongMaterial({color: 0xE68A00, ambient: 0xffffff});
var extrusionSettings = {
amount: 10,
bevelEnabled: false,
bevelThickness: 0.2,
bevelSize: 0.2,
bevelSegments: 8,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shapes, extrusionSettings);
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
UPDATE:
According to WestLangley's comment I succeeded in adding the different texture to backfaces:
// ...
var materials = [materialFront, materialSide, materialBack];
// ...
for ( var face in mesh.geometry.faces ) {
if (mesh.geometry.faces[ face ].normal.z == 1) mesh.geometry.faces[ face ].materialIndex = 2;
}
After you create your mesh geometry, and before the first call to render(), you have to change the materialIndex to 2 for the back faces. Then, add a third material in your material array.
You can identify the back faces by their face normals. Face normals for faces on the back of the geometry should all point in the same direction.
three.js r.58
Try using:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture, side: THREE.FrontSide });
var materialSide = new THREE.MeshPhongMaterial({ color: 0xE68A00, ambient: 0xffffff, side: THREE.BackSide });
even though you should probably lower your ambient contribution and give a color to the FrontSide material.
Then:
var materials = [materialFront, materialSide];
scene.add( THREE.SceneUtils.createMultiMaterialObject( geometry, materials ));
I'm trying to make a double-sided mesh with THREE.MeshLambertMaterial, but only the front side is shaded. It works fine when I use THREE.MeshBasicMaterial. I am using the THREE.WebGLRenderer, version 57.
Here's a simplified example with a rectangle:
var rectWidth = 100, rectLength = 100;
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(0, rectWidth, 0));
geometry.vertices.push(new THREE.Vector3(rectLength, rectWidth, 0));
geometry.vertices.push(new THREE.Vector3(rectLength, 0, 0));
geometry.vertices.push(new THREE.Vector3(0, 0, 0));
geometry.faces.push(new THREE.Face4(0, 1, 2, 3));
// MeshBasicMaterial works
var material = new THREE.MeshLambertMaterial({
color: 0xCC0000,
side: THREE.DoubleSide,
});
geometry.computeFaceNormals();
geometry.computeVertexNormals();
var rect = new THREE.Mesh(geometry, material);
scene.add(rect);
What am I doing wrong? I found http://mrdoob.github.com/three.js/examples/webgl_performance_doublesided.html, which shows that THREE.DoubleSide works with THREE.MeshPhongMaterial (which also didn't work in my case). The example uses a built-in geometry though, whereas I am building a custom one, so I suppose I am missing something there.