How to get size of PlaneGeometry in three.js - javascript

I made mesh with PlanGeometry and BasicMaterial.
function createMesh(width, height) {
let geometry = new THREE.PlaneGeometry(width, height);
let mat = new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: true,
side: THREE.DoubleSide,
opacity: 0.5
});
return new THREE.Mesh(geometry, mat);
}
And I used this mesh in other place and make transformed this mesh.
So
mesh.matrix.identify();
mesh.applyMatrix(matrix); // make some transform.
Now, I want to get size of plane geometry
So I tried with following method.
let boundingBox = new THREE.Box3().setFromObject(mesh);
let size = new THREE.Vector3(0,0,0);
size = boundingBox.getSize(size);
console.log('size', size);
But size is not correct.
How can I get width, height value when created PlaneGeometry (width, height) before?
let geometry = new THREE.PlaneGeometry(width, height);
I want to know width, height value upper code.
Please anyone help.

You will probably have better results by checking the bounding box, geometry.parameters is not a reliable object - it's only created for primitives, and is not updated when the object is manipulated, so it won't reflect any scale changes.
mesh.geometry.computeBoundingBox()
const size = mesh.geometry.boundingBox.getSize()
console.log('size', size);

I found a answer.
let parameters = mesh.geometry.parameters;
let size = {
width: parameters.width,
height: parameters.height
};
console.log('size', size);
Thanks #prisoner849.

Related

How can I scale down a mesh in three.js

I have a mesh that I want to scale down (shrink) in three.js.
I've tried the following code with no hope:
Can anyone advise please?
drawMesh(vAngles, hAngles, intensities) {
let vLines = this.getVerticalDistribution(vAngles, hAngles, intensities);
let hLines = this.getHorizontalDistribution(vAngles, hAngles, intensities);
let mesh = new THREE.Mesh();
mesh.add(...vLines);
mesh.add(...hLines);
mesh.rotation.y = Math.PI;
mesh.scale.set(0.25,0.25, 0.25);
mesh.matrixAutoUpdate = true;
}
When I set the scale value to 0.05 the Mesh get scaled down, so I think the units used needed to match the scale ratio.

Positioning of mesh with respect to it's parent

I'm working on a project in which I create 3d Widget to rotate, scale and translate a mesh.
I'm currently having some trouble with positioning the cone that I use for scaling the parent mesh.
This is my code:
function createScaleWidget(mesh, constScale){
var bbox = new THREE.Box3().setFromObject(mesh);
var material = new THREE.MeshBasicMaterial({
color: 0x0000ff
});
var coneGeom = new THREE.CylinderGeometry(0, constScale, 10, 50, 20, false);
var cone = new THREE.Mesh(coneGeom,material);
cone.position.y = bbox.max.y/2; //assuming all the objects are laid on the ground
cone.position.z = bbox.max.z+10;
cone.position.x = bbox.max.x+10;
mesh.add(cone);
}
mesh is the mesh I'm creating the widget for,
cone is the widget.
I would like to have the cone in the middle of the mesh (with respect to y)
and in an angle with respect to the bounding box (the ideal would be to have it on the right of the face bounding box that is facing the camera).
Probably my problem is due to the fact that the cone is child of the mesh therefore the final position do not only depends on the bbox but also on the position of the mesh itself.
I guess you want something like that:
You are right you have to locate the cone relatively to its parent position, in this case - the mesh:
function createScaleWidget(mesh, constScale){
var bbox = new THREE.Box3().setFromObject(mesh);
var material = new THREE.MeshBasicMaterial({
color: 0x0000ff
});
var coneGeom = new THREE.CylinderGeometry(0, constScale, 10, 50, 20, false);
var cone = new THREE.Mesh(coneGeom,material);
cone.position.y = bbox.size().y / 2;
mesh.add(cone);
}
this worked for me while i did something similar. the cone should be placed next to one of the faces. to try another face you can then try:
cone.position.z = bbox.size().z / 2;
instead.

How would I create a terrain like this in Three.js

I am trying to create a terrain from a heightmap with a "closed" bottom see the example here:
http://demos.playfuljs.com/terrain/
My terrain generation function is as so:
var img = document.getElementById("landscape-image");
var numSegments = img.width - 1; // We have one less vertex than pixel
var geometry = new THREE.PlaneGeometry(2400, 2400, numSegments, numSegments);
var material = new THREE.MeshLambertMaterial({
color: 0xccccff,
wireframe: false
});
plane = new THREE.Mesh(geometry, material);
plane.name = 'Terrain';
// set height of vertices
for (var i = 0; i < plane.geometry.vertices.length; i++) {
plane.geometry.vertices[i].z = (terrain[i]/255) * height;
}
geometry.computeFaceNormals();
geometry.computeVertexNormals();
plane.position.x = 0;
plane.rotation.x = 0;
plane.position.y = -10;
The problem I am having is how do I create that connected bottom part of the terrain with a THREE.PlaneGeometry. I can't extrude as:
The bottom must be flat if I extrude it will be bumpy like the
terrain.
Extrude takes a Shape object, not a Geometry object.
Really scratching my head here anyone done this before.
Edit: Maybe I could use two planes and merge them but how would I merge the side faces into a single piece of Geometery ?
P.S. The example draws straight to the canvas
create a plane for each side which has your amount of Segments in width and 1 in height. them set the top Vertices according to your heightmap
something like this
var geometry_l = new THREE.PlaneGeometry(2400, 0, numSegments, 1);
plane_l = new THREE.Mesh(geometry_l, material);
for (var i = 0; i < numSegments; i++) {
plane_l.geometry_l.vertices[i].z = (Terrain[0][i]/255) * height;
}
//Offset to the edge of your main plane
you might want to Change your Terrain Array to be two-dimensional for this. so you can always read the row you want.

three.js edges and text jagged/blurry on rotation

I'm a three.js beginner. Trying to apply an html canvas as texture to plane geometry. Works fine when there is no rotation. When rotated, a) outside edges of the mesh become jagged (edges/lines within the image are fine) and b) text becomes blurry.
What do I have to do to keep outside edges and text crisp?
My texture is power-of-two (128 x 512). Turning antialiasing on doesn't help.
Here is a screenshot without rotation
And here with rotation.
Code looks like this:
var eltTexture = toTexture2(d, this, go.w, go.Res.ow[0]);
// map texture to material
var material = new THREE.MeshBasicMaterial(
{ map : eltTexture } );
//define sub image of texture to be applied to mesh
var cutout = [
new THREE.Vector2(0, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, 1),
new THREE.Vector2(0, 1)];
// geometry and UV mapping
var geometry = new THREE.PlaneGeometry (go.w, go.Res.ow[0]);
geometry.faceVertexUvs[0] = []; // initialize
geometry.faceVertexUvs[0][0] =
[cutout[3], cutout[0], cutout[2]];
geometry.faceVertexUvs[0][1] =
[cutout[0], cutout[1], cutout[2]];
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(d.threeX, d.threeY, d.threeX);
mesh.rotation.set(0,0.6,0);
scene.add( mesh );
});
renderer.render( scene, camera );
function toTexture2 (d, svgNode, svgWidth, svgHeight){
// step 1: serialize eltSVG to xml
var eltXML = new XMLSerializer().serializeToString(svgNode);
eltXML = 'data:image/svg+xml;charset = utf8,' + eltXML;
// step 2: draw eltXML to image
var eltImage = document.body.appendChild(
document.createElement("img"));
eltImage.id = "eltImage";
eltImage.style.display = "none";
eltImage.width = svgWidth;
eltImage.height = svgHeight;
eltImage.src = eltXML;
// step 3: draw image to canvas
// NOTE: define canvas parameters position, width and
// height in html, NOT IN CSS, otherwise image
// will become blurry - don't ask why!
var eltCanvas = document.body.appendChild(
document.createElement("canvas"));
eltCanvas.id = "eltCanv";
eltCanvas.style.display = "none";
eltCanvas.width = 512;
eltCanvas.height = 128;
// get context
var ctx = eltCanvas.getContext("2d", {alpha: false});
// draw svg element to canvas, not including portrait image
ctx.drawImage(eltImage, parseInt(0), parseInt(0),
svgWidth, svgHeight);
// draw portrait image to canvas
var portrait = document.getElementById(d.nameConcat + "Img");
ctx.globalAlpha = 0.6; // opacity of portrait image
ctx.drawImage(portrait, go.Res.strw[0], go.Res.strw[0],
go.Res.iw[0], go.Res.iw[0]);
var texture = new THREE.Texture(eltCanvas);
texture.needsUpdate = true;
return texture;
} // function toTexture2
Many thanks in advance for your help!
Even though it's been a long time since you've posted this, I have the solution in case anyone else is experiencing the same issue.
Add this to your renderer:
const renderer = new THREE.WebGLRenderer({antialias: true});

Three.js - bind a texture to particle

My question is how can I bind texture to a particle in
use of THREE.ParticleCanvasMaterial ?
I mean what is the syntax to bind texture to particle?
You should try to use a ParticleBasicMaterial and pass in your Texture as the map property of the material:
var material = new THREE.ParticleBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'yourTexture.png' ) } );
Also, have a look at the canvas_particle_sprites example. Notice that it's generating a texture on the fly, but you can load your own texture as described above. From experience, the CanvasRenderer is slow with many/large textures.
Update 2019: ParticleBasicMaterial is deprecated
ParticleBasicMaterial has been renamed to PointsMaterial.
https://threejs.org/docs/#api/en/deprecated/DeprecatedList
You need to use PointsMaterial instead of ParticleBasicMaterial
var snowMaterial = new THREE.PointsMaterial({
size: 7,
blending: THREE.AdditiveBlending,
map: new THREE.TextureLoader().load("./assets/snowflake.png"),
//createCircleTexture("#ffffff", 20),
transparent: true,
depthWrite: false
});
Alternatively you can use canvas to draw Circular shapes for particle texture as suggest by George:
export const createCircleTexture = (color, size) => {
var matCanvas = document.createElement("canvas");
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext("2d");
// create texture object from canvas.
var texture = new THREE.Texture(matCanvas);
// Draw a circle
var center = size / 2;
matContext.beginPath();
matContext.arc(center, center, size / 2, 0, 2 * Math.PI, false);
matContext.closePath();
matContext.fillStyle = color;
matContext.fill();
// need to set needsUpdate
texture.needsUpdate = true;
// return a texture made from the canvas
return texture;
};
Test Image
Result

Categories