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

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

Related

Find object dimensions in three.js

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)

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.

HTML5 Canvas - Scaling relative to the center of an object without translating context

I'm working on a canvas game that has several particle generators. The particles gradually scale down after being created. To scale the particles down from their center points I am using the context.translate() method:
context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
context.restore();
I've read several sources that claim the save(), translate() and restore() methods are quite computationally expensive. Is there an alternative method I can use?
My game is targeted at mobile browsers so I am trying to optimize for performance as much as possible.
Thanks in advance!
Yes, just use setTransform() at the end instead of using save/restore:
//context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
//context.restore();
context.setTransform(1,0,0,1,0,0); // reset matrix
Assuming there are no other accumulated transform in use (in which case you could refactor the code to set absolute transforms where needed).
The numbers given as argument are numbers representing an identity matrix, ie. a reset matrix state.
This is much faster than the save/restore approach which stores and restores not only transform state, but style settings, shadow settings, clipping area and what have you.
You could also combine the two translation calls into a single call, and use multiply instead of divide (which is much faster at CPU level):
context.translate(particle.x-particle.width*0.5, particle.y-particle.height*0.5);
or simply use the x/y coordinate directly with the particle "shader" without translating at all.

Three.js - Rotation not respecting local orientation

I'm using a large array of objects built around a center point in a scene, and need to manipulate them all around their local axis. They are all facing the origin using a blank object and lookAt(), then I used this method to align the other axes correctly. Getting the initial rotation this way worked great, unfortunately when I try to rotate these objects on the fly with object.rotation.x = <amount>, it does not respect the local axis of the object.
The confusing part is, it's not even using the global axis, the axis it's using almost seems entirely arbitrary. I set up a JSFiddle to demonstrate this here. As you can see on line 129, looker.rotation.z works correctly, it rotates along the Z axis properly, but if it's changed to X or Y, it doesn't rotate along local or global axes. If anyone could demystify what is happening to cause this, that would be great.
What is happening is that you want to add some rotation to the current orientation, and setting the variable looker.rotation.z means other thing.
At the end, to calculate the rotation matrix of the looker, there will be something like (pseudocode: the functions are not these, but you get the idea):
this.matrix.multiply( makeXRotationMatrix(this.rotation.x) )
this.matrix.multiply( makeYRotationMatrix(this.rotation.y) )
this.matrix.multiply( makeZRotationMatrix(this.rotation.z) )
DrawGeometry(this.geom, this.matrix)
and composition of rotations are not intuitive. This is why it doesn't seem to follow any axis system.
If you want to apply a rotation in some axis to the existing matrix, it can be made with the functions rotateX (angle), rotateY (angle), rotateZ (angle), and rotateOnAxis (axis, angle). axis can be a THREE.Vector3.
Changing directly looker.rotation.z works because it is the nearest rotation to the geometry, and it will not be affected by the other rotations (remember that transformation matrices apply in inverse order, e.g. T*R*G is Rotating the Geometry, and then, Translating it).
Summary
In this case I suggest not to use the line:
looker.rotation.z += 0.05;
Use
looker.rotateZ (0.05);
or
looker.rotateX (0.05);
instead. Hope this helps :)

Creating a Transformation Pipeline in Three JS

I'm struggling to explain my problem, so please bear with me.
Is there a recommended way to re-apply the same transformations to an object in it's original shape for every frame, so that one can easily see the differences as the transforms changes the original object. In the pseudocode below, there is an "original object". In each frame, we apply the current transforms to the original object so we can see the differences.
UI Slider: Scale
UI Slider: Rotate
UI Slider: Position
For each frame {
Original Object -> ApplyCurrentScale -> ApplyCurrentRotate -> ApplyCurrentPosition
Render New Object
}
This way, as you change the transforms, in real time, you can watch the effect. I hope this makes sense.
Here is the pattern to follow, after you extract the parameters from the sliders:
object.scale.set( s, s, s );
object.setRotationFromAxisAngle( axis, angle ); // r.59
object.position.set( x, y, z );
renderer.render( scene, camera );
Another way to set the rotation is:
object.rotation.y = angle;
three.js r.59

Categories