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
Related
I'm trying to animate the lookAt method of an Object3D to lookAt a target Vector3. My Tween function traces floating points as per the incrementing scalarMultiplyVal (0.0 - 1.0), but no matter what I try the Object3D is already looking at the target before the tween starts. Very odd.
TweenMax.to( this, 5, {scalarMultiplyVal:1, onUpdate:function(){
let targetVector = new THREE.Vector3( target.position.x, target.position.y, target.position.z ).multiplyScalar( scalarMultiplyVal );
console.log( targetVector ) // logs "animating" x,y,z values as expected
displayObject.lookAt( targetVector ); // does not animate. Already fulling looking at target.position ( scalarMultiplyVal = 1.0 )
}});
Essentially I'm trying to have my Object3D animate/turn to look at a new vector3 periodically, but instead the Object3D is already fully looking at the target.position, and disregarding the vector multiplication. Very odd. Any advice will be a great help!
Instead of performing an animation with Object3D.lookAt() I highly recommend to use Quaternion.rotateTowards(). The method is based on Unity's Quaternion.RotateTowards. It internally performs a slerp which is ideal for your use case. The following example demonstrate the usage of Quaternion.rotateTowards().
https://threejs.org/examples/webgl_math_orientation_transform
three.js R104
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.
For each mesh (THREE.Object3D) Three.js provide a very handy properties - boundingSphere and boundingSphere that have intersectsSphere and isIntersectionBox methods.
With all this I thought I can use it for simple collision detection but when I try it appears that collision happens all the time because (I tried boundingSphere) boundingSphere.center is always in (0, 0, 0); So If I want to check collisions between 2 meshes I should for each object - clone boundingSphere object and then get it world coordinates and only then to use intersectsSphere.
something like this:
var bs = component.object.geometry.boundingSphere.clone();
bs.center.setFromMatrixPosition(component.object.matrixWorld);
...
if (_bs.intersectsSphere(bs)){
is this how it suppose to be used or am I missing something and there are more convenient way of doing collisions detection based on boundingBox/boundingSphere?
If you want to do collision detection with bounding boxes you need the boxes in the world coordinate system. The bounding volumes in the intersectsSphere and isIntersectionBox properties of the mesh are in the local coordinate system of the object.
You can do like you did: clone the volumes and move them to the correct position in the world coordinate system, that is a good solution.
Otherwise you can also set a new box from your meshes and do collision using those boxes. Let's say you have a THREE.Mesh called mesh then you can do:
sphere = new THREE.Sphere.setFromPoints( mesh.vertices );
box = new THREE.Box3.setFromObject( mesh );
A little tip. During development it can be nice to see the bounding boxes in your scene, for this you can use the THREE.BoundingBoxHelper:
var helper = new THREE.BoundingBoxHelper( mesh );
scene.add( helper );
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 :)
In a three.js project, I'm using a modified version of PointerLockControls.js for the camera control. I want to modify the rotation functionality so that there is no absolute "up" axis by which the camera rotates, but rather moving the mouse up or down will pitch indefinitely, same for left and right for yawing (and keys for rolling).
I can't seem to get the yawing component working, as it seems to rotate around the same axis regardless of pitch. (ie moving left or right when face facing straight upwards will just rotate the camera)
Any help in the right direction would be great!
I had the same problem recently, so I had a look at some of the THREE.*Controls files, similar to you.
Using those as a basis, I made this:
https://github.com/squarefeet/THREE.ObjectControls
The important bits are the following (see here for context):
var updateTarget = function( dt ) {
var velX = positionVector.x * dt,
velY = positionVector.y * dt,
velZ = positionVector.z * dt;
rotationQuaternion.set(
rotationVector.x * dt,
rotationVector.y * dt,
rotationVector.z * dt,
1
).normalize();
targetObject.quaternion.multiply( rotationQuaternion );
targetObject.translateX( velX );
targetObject.translateY( velY );
targetObject.translateZ( velZ );
};
The rotationVector is probably of most interest to you, so here's what it's doing:
It's using a THREE.Vector3 to describe the rotation, the rotationVector variable in this example.
Each component of the rotationVector (x, y, z) is relative to pitch, yaw, and roll respectively.
Set a quaternion's x, y, and z values to the of the rotation vector, making sure the w component is always 1 (to learn what the w component does, see here, it's a great answer.
Normalizing this quaternion will get us a quaternion of length 1, which is very handy when we come to the next step...
targetObject in this case is an instance of THREE.Object3D (a THREE.Mesh, which inherits from THREE.Object3D), so it has a quaternion we can play with.
So now, it's just a matter of multiplying your targetObject's quaternion by your shiny new rotationQuaternion.
Since our object is now rotated to where we want, we can move it along it's new axis angles by using translateX/Y/Z.
The important thing to note here is that quaternions don't act like Euler vectors. Rather than adding two quaternions together to get a new angle, you multiply them.
Anyway, I hope that helps you somewhat!