Three.js outline mesh - three.js

How can I get outline affect the same as in THREE.js editor ?
I've tried this:
// child = child of my object
var outlineMaterial1 = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.BackSide } );
var outlineMesh1 = new THREE.Mesh( child.geometry, outlineMaterial1 );
outlineMesh1.position = child.position;
outlineMesh1.scale.multiplyScalar(1.05);
scene.add( outlineMesh1 );
Trying to do the same as in this example (code). I'm getting completely different effect:
Same questions: #1 and #2.

Did you try wireframe?
var outlineMaterial1 = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.BackSide, wireframe: true } );
Not sure if you would need THREE.BackSide or not.
take a look at the parameters for MeshBasicMaterial here
Have you looked at the code for the editor to see how it does it?
EDIT
I think the editor is using a BoxHelper object which creates the outline
EDIT
HERE is a stack question showing how to have the BoxHelper render on top.
HERE is a fiddle as an example implementing the above.

If you need somethink of this when user tap on mesh you can use this code :
let geo = new THREE.EdgesGeometry(intersects[0].object.geometry);
let mat = new THREE.LineBasicMaterial({ color: "black", linewidth: 10 });
let wireframe = new THREE.LineSegments(geo, mat);
wireframe.renderOrder = 1; // make sure wireframes are rendered 2nd
intersects[0].object.add(wireframe);

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.

ThreeJS remove texture

I have a ThreeJS scene and I'd like to provide the option of seeing all models in different modes (with or without textures and/or wireframe).
I'm trying to accomplish this using only one Geometry and one Material for each object.
When I try to remove the texture of an object by setting the map property of its material to null something bizarre happens. The object takes the latest loaded texture, even if it was loaded and applied to another object. Is this somehow an expected behavior? If not, how should I remove the map?
a good approach would be to initialize the materials you will need from the beginning :
var materials = {};
materials['lambert'] = new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading } );
materials['phong'] = new THREE.MeshPhongMaterial( { color: 0xFF0000, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } );
materials['basic'] = new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } );
materials['wireframe'] = new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe : true } );
and replace the material of your object when you need to :
function changeMaterial(id){
mesh.material = materials[id];
}
changeMaterial('wireframe');
I did a fiddle that demonstrates that : http://jsfiddle.net/95t964o0/75/
I did not use a material with a texture because it's a bit tricky for jsfiddle.com to load an image.
Note : be carefull when many objects share the same material! If you make changes to the material of an object it affects all the others (obviously because it is shared).

Threejs How to assign different color for top face of a cylinder?

I would like to create a simple cylinder and color its top face differently. I can create the cylinder and assign a material. My recent code:
var zylinder = {};
zylinder._width = 1;
zylinder._height = 1;
zylinder._color = 0xFF666e;
var cyl_material = new THREE.MeshLambertMaterial({
color: zylinder._color,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.9,
// map: THREE.ImageUtils.loadTexture( "texture-stone-wall.jpg" ),
});
var cylGeometry = new THREE.CylinderGeometry(zylinder._width, zylinder._width, zylinder._height, 20, 1, false);
var cylinder = new THREE.Mesh(cylGeometry, cyl_material);
cylinder.position.y = zylinder._height/2+0.001;
scene.add(cylinder);
Using console.log( cylGeometry.faces ); I see that there are about 80 objects.
I tried changing the face colors by:
cylGeometry.faces[0].color.setHex( 0xffffff );
cylGeometry.faces[1].color.setHex( 0xffffff );
// ...
but it does not work, maybe due to THREE.MeshLambertMaterial.
Recent version (includes shading): Zylinder: Volumen berechnen online - Formel interaktiv
How can I assign a different color for the top face? Do I need to use another material?
You can use another material for the end caps, but you don't have to.
Instead, you can use this pattern: For each end cap face, set
geometry.faces[ faceIndex ].color.set( 0x00ff00 );
...
And then set
material.vertexColors = THREE.FaceColors;
You can indentify the end cap faces by their face.normal, which is parallel to the y-axis.
If you want to use a separate material for the end caps, you need to set for each end cap face, face.materialIndex = 1 ( the default is 0 ), and then create your mesh using this pattern:
var materials = [ new THREE.MeshBasicMaterial( { color: 0xff0000 } ), new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) ];
var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
three.js r.68

three.js add border to material by materiel name on loaded models

is it possible to add border around a material, as attached in the image,
i can set the material color by following code
object.traverse( function ( child )
{
if ( child instanceof THREE.Mesh )
child.material.color.setRGB (1, 0, 0);
});
where object is my loaded 3d model, so am assume there should be a way to draw the border, is there any option in three.js.
As per the #shiva's comment i have tried it with the following code to draw the glow effect
if(childObject.material.name=="material4046")
{
mesh = new THREE.Mesh( globalGeomtry, material );
// mesh.visible = false
scene.add( mesh );
console.log(mesh);
// create a glowMesh
var glowMesh = new THREEx.GeometricGlowMesh(mesh);
mesh.add(glowMesh.object3d);
// example of customization of the default glowMesh
var insideUniforms = glowMesh.insideMesh.material.uniforms;
insideUniforms.coeficient.value = 2;
insideUniforms.power.value = 1.4;
insideUniforms.glowColor.value.set('red');
var outsideUniforms = glowMesh.outsideMesh.material.uniforms;
outsideUniforms.coeficient.value = 2;
outsideUniforms.power.value = 1.4;
outsideUniforms.glowColor.value.set('red');
}
now the ouput is looking as like in the second image,
i want this glow effect as the border around that material, is it is possible
I think this is what you were after. It is achieved with:
new THREE.MeshBasicMaterial( { color: 0x00ff00, side: THREE.BackSide } );
You can see a demo here:
https://stemkoski.github.io/Three.js/Outline.html
Source code of the demo: https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Outline.html
I tried my level best to achieve it, but unfortunately I can't get it, so I decided to do it with the wireframe option to highlight the material:
if(childObject.material.name=="material9695")
{
var mesh = new THREE.Mesh( globalGeomtry, material );
scene.add( mesh );
var outlineMaterial1 = new THREE.MeshBasicMaterial( { color: 0xff0000,wireframe : true } );
var outlineMesh1 = new THREE.Mesh( globalGeomtry, outlineMaterial1 );
scene.add( outlineMesh1 );
}
Now the wireframe is added for the material material9695 so I can identify that the material material9695 is currently selected
This is not the exact answer I expected but it is enough right now after some hard hours

How to create multiple Box and only change the texture on one side?

I'm trying to apply a texture to only one side of a Box Object.
Basic code:
BoxGeo = new THREE.BoxGeometry(50, 50, 125);
BoxMat = new THREE.MeshLambertMaterial({ color: 0xF0F0F0 });
BoxObj = new THREE.Mesh(GeoBox, GeoMat);
I tried using an array containing 6 materials object, 5 colored and one with an image (randomly choosed from another array of textures for each Box). But it throws an error :(
Is it possible to provide a simple exemple of a Box with different texture for each face?
I saw some exemple on the internet but they require to put the material array inside the Geometry object and I would like to avoid creating a new Geometric object for each Box for performance reasons.
What about this sample? It creates the material array and then adds it to the mesh. So, you could re-use it.
Relevant code:
// Create an array of materials to be used in a cube, one for each side
var cubeMaterialArray = [];
// order to add materials: x+,x-,y+,y-,z+,z-
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff3333 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff8800 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xffff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x33ff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x3333ff } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x8833ff } ) );
var cubeMaterials = new THREE.MeshFaceMaterial( cubeMaterialArray );
// Cube parameters: width (x), height (y), depth (z),
// (optional) segments along x, segments along y, segments along z
var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
// using THREE.MeshFaceMaterial() in the constructor below
// causes the mesh to use the materials stored in the geometry
cube = new THREE.Mesh( cubeGeometry, cubeMaterials );

Resources