How can I control line width using the THREE.js createMultiMaterialObject function? - three.js

I'm experimenting with the createMultiMaterialObject function in THREE.js to create shaded objects that also display a wireframe. The problem is the lines appear broken & don't seem to respond to the wireframeLinewidth parameter.
My materials are defined as follows:
var mat1 = new THREE.MeshBasicMaterial( { color: 0xd02000, transparent: true, blending: THREE.AdditiveBlending } )
var blackLines = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 4 } );
And the object is here:
var object = THREE.SceneUtils.createMultiMaterialObject( new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ), materials );
object.position.set( -100, 150, 0 );
scene.add( object );
But this produces this result:
Any help would be appreciated. Thanks!

Your code is fine. Are you running Windows? If so, it is possibly an ANGLE issue, in which case the line width cannot be changed. See this related question.
If you are unable to increase the line width, a work-around in your case is to make the wireframe mesh just a bit larger than the solid mesh, like so:
object.children[ 1 ].scale.multiplyScalar( 1.01 );
If you do that, there will be no more broken lines and it will be beautiful. :-)
three.js r.55

Related

How to create a Points (Mesh) of TextGeometry?

I am creating a TextGeometry but not able to convert in Points like a sphere or like a detailed 3d object.
In the below image I have created a sphere using
var dotGeometry = new THREE.SphereBufferGeometry(2, 100, 100);
var dotMaterial = new THREE.PointsMaterial({ size: 1, sizeAttenuation: false });
var dot = new THREE.Points(dotGeometry, dotMaterial);//new THREE.MeshBasicMaterial()
scene.add(dot);
and the for text I use
const fontloader = new THREE.FontLoader();
fontloader.load('./models/font.json', function (font) {
const textgeometry = new THREE.TextGeometry('Hello', {
font: font,
size: 1,
height: 0.5,
curveSegments: 12,
bevelEnabled: false,
bevelThickness: 10,
bevelSize: 8,
bevelOffset: 0,
bevelSegments: 5
});
var dotMaterial = new THREE.PointsMaterial({ size: 1, sizeAttenuation: false });
let textmesh = new THREE.Points(textgeometry, dotMaterial) //new THREE.MeshBasicMaterial({
// color: 0xffffff,
// wireframe: true
// }));
textmesh.geometry.center();
scene.add(textmesh);
// textmesh.position.set(0, 2, 0)
});
So how to create a geometry having many points for text also, Why I am not able to use MeshBasicMaterial for Points in sphere?
What you see is actually the expected result. TextGeometry produces a geometry intended for meshes. If you use the same data for a point cloud, the result is probably not as expected since you just render each vertex as a point.
When doing this with TextGeometry, you will only see points at the front and back side of the text since points in between are not necessary for a mesh.
Consider to author the geometry in a tool like Blender instead and import it via GLTFLoader.

How to export the mesh after modified the Vertices in Three.js?

I tried to export the bent text geometry in the example of https://threejs.org/examples/webgl_modifier_curve.html by OBJExporter.js. But the result text geometry exported was not bent as seen in the scene.
The code of "new OBJExporter..." was added after the code line "scene.add( flow.object3D );"
Please advise where I should put the exporter code and what steps I missed to get the text geometry with modified vertices? Great thanks for help!
const loader = new THREE.FontLoader();
loader.load( "fonts/Microsoft_YaHei_Regular.json", function (
font
) {
const geometry = new THREE.TextGeometry( "1 234567890", {
font: font,
size:0.25,
height: 0.02, //0.05 thickness
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.01,
bevelOffset: 0,
bevelSegments: 5,
} );
geometry.rotateX( Math.PI );
geometry.rotateY( Math.PI );
const material = new THREE.MeshStandardMaterial( {
color: 0x99ffff
} );
const objectToCurve = new THREE.Mesh( geometry, material );
flow = new Flow( objectToCurve );
flow.updateCurve( 0, curve );
scene.add( flow.object3D );
const exporter = new OBJExporter();
const result = exporter.parse(flow.object3D);
The vertex displacement of the modifier happens on the GPU (in the vertex shader). So you can't use any of the exporters to export the bent/modified geometry.

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 - apply different material to extruded shape

I have Three.Shape which I can apply Extrusion
To get a plane I drew a square first and then apply extrusion
var squareShape = new THREE.Shape();
squareShape.moveTo( 0,0 );
squareShape.lineTo( 0, sqLength );
squareShape.lineTo( sqLength, sqLength );
squareShape.lineTo( sqLength, 0 );
squareShape.lineTo( 0, 0 );
var geometry = new THREE.ExtrudeGeometry( squareShape,extrudeSettings);
now a 3D square is appearing on my browser.
Next I want to apply a image texture of 256x256 on its top face. How to do this?
If you look at src/extras/geometries/ExtrudeGeometry.js in THREE.js you will see these comments.
material: // material index for front and back faces
extrudeMaterial: // material index for extrusion and beveled faces
So for example you can say (obviously won't run directly because it is incomplete)
// The face material will be index #0. The extrusion (sides) will be #1.
var extrudeSettings = { amount: 10, bevelEnabled: true, bevelSegments: 3, steps: 4, bevelThickness: 8, material: 0, extrudeMaterial: 1 };
And when you create your mesh you create 2 materials and assign them to your mesh.
var mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshLambertMaterial( { color: color } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, transparent: true } ) ] );
Hope this gets you on the right path.
On a side note, related to the other answer, you make want to use extrude to create something that dimensionally is similar to a square but has bevels. One example would be if you were trying to draw dice and wanted to round the edges.
If all you want is a cube why are you extruding? Why don't you use the CubeGeometry.

Resources