Find object dimensions in three.js - javascript

Short question. How does one find the dimensions of a mesh in three.js?
I have Collada (.dae) files which I would like to know the size of in units (x,y,z). I have seen comments about using geometry.computeBoundingBox(), but I am still not exactly sure how to use it.
Also I am aware of using scale but my ultimate goal is to compare objects in the scene with realistic measurements (mm) so it helps to know the exact physical dimensions of an object so that I may change it if necessary.
Appreciate any words of wisdom :^)

Using a bounding box sounds like a good idea. You can try something like this
boundingBox = new THREE.Box3().setFromObject(your_object)
size = boundingBox.getSize() // Returns Vector3
Docs:
Box3: https://threejs.org/docs/#api/math/Box3
Vector3: https://threejs.org/docs/#api/math/Vector3
Comment update: Now that I have the object dimensions X,Y,Z, how can I change the value of let's say 'X' and have the object scale to it?
scaleFactor = otherSize.x / mySize.x
myObject.scale(scaleFactor, scaleFactor, scaleFactor)

Related

Text with inset shadow three.js

I need to create text with inset shadow on my object in three.js, which looks like this:
Something like ring with engraved text.
I think the easier way to do that would be to use a normal-map for the engraving, at least if the text doesn't have to be dynamic (here's how you can export a normal-map from blender). And even if it needs to be dynamic it might be easier to create a normal-map dynamically in a canvas than to actually create a geometry for the engraving.
Another option would be to actually create a geometry that contains the engraving. For that you might want to look at the ThreeCSG-library, that let's you use boolean operators on geometries: You create the 3D-text mesh, warp and align it to the curvature of the ring and finally subtract it from the ring-mesh. This should give you the ring with the engraving spared out.
In fact, I was curious how this would actually work out and implemented something very similar here: https://usefulthink.github.io/three-text-warp-csg/ (source here).
In essence, This is using ThreeCSG to subtract a text-geometry from a cylinder-geometry like so:
const textBSP = new ThreeBSP(textGeometry);
const cylinderBSP = new ThreeBSP(cylinderGeometry);
const resultGeometry = cylinderBSP.subtract(textBSP).toGeometry();
scene.add(new THREE.Mesh(resultGeometry, new THREE.MeshStandardMaterial());
Turns out that the tessellation created by threeCSG really slow (I had to move it into a worker so the page doesn't freeze for almost 10 seconds). It doesn't look too good right now, as there is still a problem with the computed normals that i haven't figured out yet.
The third option would be to use a combination of displacement and normal-maps.
This would be a lot easier and faster in processing, but you would need to add a whole lot of vertices in order to have vertices available where you want an displacement to happen. Here is a small piece of code by mrdoob that can help you with creating the normal-map based on the displacement: http://mrdoob.com/lab/javascript/height2normal/

Three.js mesh resize

I have a 3D model that was loaded as an obj file into Three.js. The model itself is a furniture.
The problem is, that furniture material is dynamic and is different in size (thickness). I need to have to able to made thickness of material bigger, but the total size of the model can't be changed. So scaling isn't an option.
Is there a way I can resize parts of the model (few specific meshes) and doesn't compromise the structure of mesh itself ? I need to change thickness of the structure, but internal parts of the model shouldn't change.
The only solution I can think of is to change scale of some of the meshes and then to change global position of the other meshes based on that. Is this the right way ?
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
// resize and reposition some of the meshes
}
});
Possible ways to solve it:
Bones
Deformation
Well, if all of the meshes are separate primitives, then you can just change the scale of each part you want to change along one axis, and just set up anchor points to constrain to the outside. So for pieces on the border, you scale the empty object that they're attached to so that they maintain the outer shell.
EG:
OOOOOO
OMMMMMMO
OMmmmmMO
OMmmmmMO
OMMMMMMO
OOOOOO
where O is an Object3D carrying the adjacent Mesh-M, and the m's represent meshes that are scaled themselves. This way if you adjust the scale of all 'm's and 'O's, the outer shell stays in place,
But you're on the right track with the traversal. You'll just have to do this.
For an easy way to traverse, I would give everything you want to change some attribute in their .userData object. Because in some cases you'll want to scale empty objects (O) (so that you can effectively move the anchor point) whereas at others you'll want to scale the meshes in place (m). So it's not purely a mesh based operation (since meshes want to scale from their center). Doing some tagging makes the traversal simpler:
object.traverse(function(child){
if(child instanceof THREE.Mesh){
if(child.userData.isScalable){
//do the scaling.
}
}
});
and if you set up the heirarchy and .userData tagging correctly, then you just scale things and you keep the outer shell.
Is this what you're asking? because the question is unclear.
You could use Clara.io, it is built on top of ThreeJS and allows for you to run operators on geometry that you setup in Clara.io scenes. There is a thickness operator in Clara.io that you can use.
Documentation here: http://clara.io/learn/sdk/interactive-experiences
Anything you can do in the Clara.io editor you can do in an interactive-embed.
You can use your method of changing different meshes sizes and other positions, but when you use object.scale.set( x, y, z ); the browser has to change the scale of the model for every frame rendered. So if you use this for lots of meshes, it can decrease your game's performance. The best way to go would be to use a 3d editor like Blender. It is easier and more efficient.

Apply transformation to the matrix and reset values on Three.js

I'm having an issue with my 3D manipulation application. I'm using the THREE.JS. What I'm trying to do is change the scale of one object, apply this transformation to the original matrix and then restore the values of scale to 1.
I need to restore the transformation because some functions used by the UI are using this information. So, basicaly I want to considere this new size as the original size, without any transformations.
Is there any way to do that? I did some research but none of the answers has solved my issue.
var scale = 0.5;
object.scale.set(scale, scale, scale);
https://stackoverflow.com/a/27023024/3866399
Fixed with this, but I hade to change:
object.geometry.applyMatrix( object.matrix );
to
insertedPrintable.object.children[0].geometry.applyMatrix(cloneMatrix);

Three.js - Getting the low poly look

I'm trying to generate some terrain in the low poly style, for reference, this kind of style:
What I mean by this is each triangle is one shade.
When I attempt something like this, the shading is very smooth. Here's an example with only a few triangles:
(source: willdonohoe.com)
I also tried adding shadows, but this didn't create the desired effect either. Here's a shot with more triangles with added shadows:
(source: willdonohoe.com)
Looking through the Three documentation, the shading property on the materials class sounds like it would do the trick, but THREE.FlatShading and THREE.NoShading doesn't seem to have any effect.
Is there a special technique that I need to use create this effect? Any direction you can point my way would be much appreciated.
You can find my first demo here
Many thanks,
Will
EDIT: This answer was outdated. Updating:
material.shading = THREE.FlatShading is now material.flatShading = true.
You modified the vertex positions of your PlaneGeometry.
To generate flat shading with MeshLambertMaterial, you must update your normals by calling
geometry.computeFlatVertexNormals();
For other materials, simply setting material.flatShading = true is sufficient to get the flat look.
three.js r.87

Making a rotation around a point

I'm using THREE API in order to realize some animations in my app. Now i have a real problem : i'd like making spherical rotation around a specific point. The "rotate" method included in mesh objects allow me to make them, but the center of the rotation is (by default i guess) the center of the mesh.
Then, i only rotate my objects around themself...
I have already found some examples, but they don't solve my problem. I tried to create objects 3D parents like groups, and tried to make the rotation around this groups after having translated them, but this still does not work...
Can you please give me a hand about that ?
I'm so sorry, i found my problem... Making a jsfiddle made me realize i forgot to instanciate my parent as " a new Object 3D() ", that was why i didn't see any objects in my scene when i used animation on my parent... i give you a short part of my code anyway dedicated to interested people finding any help :
// mesh
mesh = new THREE.Mesh( geometry, material );
parent = new THREE.Object3D();
parent.add(mesh);
// if i want my rotation point situated at (300;0;0)
parent.position.set(300,0,0);
mesh.position.set(-300, 0, 0);
scene.add(parent);
http://jsfiddle.net/KqTg8/6/
Thank you

Categories