Using multiple materials with THREE.CylinderGeometry - create a wheel from cylinder - three.js

I want to create a wheel from cylinder (because importing 3D models makes it slower). But I cannot use multiple materials with cylinder geometry. It uses only the first material in an array.
var geometry = new THREE.CylinderGeometry(this.diameterWheel/2,this.diameterWheel/2,this.lastikGenisligi, 20, 4);
var materialArray = [];
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x000000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( '../textures/wheel.png' ) }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x0000FF }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0xFF0000 }));
var material = new THREE.MeshFaceMaterial(materialArray);
var mesh = new THREE.Mesh(geometry, material);
What I want to create is a wheel which will have wheel.png wheel image on upper and bottom sides and black coverage on between them.

You need to loop through each face on the cylinder and tell which of the array materials the face uses.
geometry.faces[a].materialIndex = b;
Where a is the face index. You need to figure out yourself which face is which to choose the correct material through some system, ie. faces 0-10 with one color, etc. This depends on the cylindergeometry parameters. And b is the material index.

Related

Life like paper in three.js

I am building a game. In my game is a scene where the character is reading a book. I have created pages of that book which should flip around and stuff. Using Three.js It is simple to crate a cube geo with some specs. My problem is that the paper or page representation is like a board. The paper should be floppy and flexible like paper.
That is where I am stuck. I looked into Physi.js but seems to be an overkill. Collision may be something I need in the future so that the pages do not assume the same exact plane, but for now I will settle for life-like. I looked at morphing but am unsure if that is the way to go.
I Have built a fiddle at https://jsfiddle.net/e4hqdjbz/
It is only a single page with orbit controls though.
//PAPER
frontside = new THREE.TextureLoader().load( 'https://images.pexels.com/photos/2837975/pexels-photo-2837975.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260' );
frontside.minFilter = THREE.LinearFilter;
backside = new THREE.TextureLoader().load( 'https://images.pexels.com/photos/1001780/pexels-photo-1001780.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260' );
backside.minFilter = THREE.LinearFilter;
edge = new THREE.TextureLoader().load( );
edge.minFilter = THREE.LinearFilter;
materialArray1= [
new THREE.MeshBasicMaterial( { color: 0xffffff } ), //Right side
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Left Side
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Top
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Bottom
new THREE.MeshBasicMaterial( { map: frontside } ),
new THREE.MeshBasicMaterial( { map: backside } ),
];
var geometry1 = new THREE.BoxGeometry( 23.3, 50, 0.005 );
var paper = new THREE.Mesh( geometry1, materialArray1 );
paper.position.set(0,0,0)
scene.add( paper );
Any thoughts on a direction I should head and why?
When flipping a page or paper, the animation should be more life-like, kinda flexible but not resistant. Adding physics with gravity, density and airflow may be the answer, but not sure.
Create a skinned mesh animation of the exact textured page animation, in Blender, either by you, or a 3d artist... export that animation as (gltf) .glb and load that in your app, and after the load completes, swap out the material.map s to whatever texture you want.

Three.js Multi-tile UV

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

threejs relation between mesh position and its binded geometry vertices position

I am looking for a way to manipulate a bundle of objects, usually one trick is to make groups, put objects as a group's children. But it is not working properly in my case.
What I want to do is binding a geometry and its wireframe together so I can manipulate them together. In the case of cube, I used a BoxGeometry and a BoxHelper. I created a mesh with BoxGeometry and created BoxHelper of the mesh. Then I want to translate/rotate/scale this bundle.
I did: geometry.applyMatrix( new THREE.Matrix4().makeTranslation(x, y, z) );
and I add this geometry to parent which worked fine.
But I notice the parent and mesh position is (0, 0, 0), and the BoxHelper position is (0, 0, 0) too. Why is the value not changing along with the geometry vertices? Is the position of an Object3D/Mesh/geometry a relative position to the its parent or in world space?
I tried to apply matrix to the parent. The result is, the mesh is in the right position but the frame is way off. Can anyone explain that? Thank you.
var newcube = new THREE.BoxGeometry(20, 20, 20);
// newcube.applyMatrix( new THREE.Matrix4().makeTranslation(x, y, z);
var mats = [];
mats.push(new THREE.MeshBasicMaterial({ color: 0xffd500 }));
mats.push(new THREE.MeshBasicMaterial({ color: 0x009e60 }));
mats.push(new THREE.MeshBasicMaterial({ color: 0x0051ba }));
mats.push(new THREE.MeshBasicMaterial({ color: 0xffffff }));
mats.push(new THREE.MeshBasicMaterial({ color: "yellow" })); // backward
mats.push(new THREE.MeshBasicMaterial({ color: 0xC41E3A }));
var faceMaterial = new THREE.MeshFaceMaterial(mats);
var parent = new THREE.Object3D();
var mesh = new THREE.Mesh(newcube, faceMaterial);
parent.add(mesh);
var cubeframe = new THREE.BoxHelper( mesh );
cubeframe.material.color.set( 0x0066ff );
parent.add( cubeframe );
parent.applyMatrix( new THREE.Matrix4().makeTranslation(x, y, z);
scene.add(parent);
objects.push(parent);

Different material on back and frontside of extruded shape

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 ));

invert mesh in three.js

How to invert a mesh using three.js
I had a mesh created using THREE.Mesh
var geometry = new THREE.ExtrudeGeometry( featurePts,extrudeSettings);
var mat = new THREE.MeshBasicMaterial( { color: color, wireframe: true, transparent: true } );
var mesh = new THREE.Mesh(geometry, mat );
But my shape looks inverted. Is there any way in Three.js to invert my shape?
shape used above is a list of THREE.Vector2
var featurePts = [];
featurePts.push(new THREE.Vector2 (550,107));
If you mean it looks inside out, try reversing your normals.

Resources