three.js - fix rotation axis of tube geometry - javascript

I've a tube geometry built with 2000 points stored as JSON data.
The tube has band (curves) also. I am using TrackBallControls.
Now when I rotate the tube, it is rotated in all three dimensions.
The rotation is not limited to any particular axis.
I am using following code after creating tubeMesh.
// to make rotation only on x-axis
var v = new THREE.Vector3(1,0,0).normalize();
var matrix = new THREE.Matrix4();
tubeMesh.applyMatrix(matrix.makeRotationAxis(v, 0));
tubeMesh.applyMatrix(matrix.makeTranslation(0,-1500,0));
if ( tube.debug ) tubeMesh.add( tube.debug );
scene.add(tubeMesh);
This code does not work as the tube is rotating on all three dimensions.
Even I've tried the functions defined in below question.
three.js rotation
How do fix the rotation axis so that the tube will be rotated only on specified axis ?
using r53

Related

Force camera.lookAt to maintain current Z rotation

So, I'm putting together a 3D project that will eventually make it's way onto a kiosk in the office of a client, basically shows all of their branches as points on a globe. One of the features requested is that end users be able to swipe on the screen to orbit around the globe, in addition, they should be able to rotate the camera on it's Z axis via a rotation gesture. The problem is I'm using camera.lookAt in the animation loop, which relies on the up vector being updated correctly whenever I rotate the camera in order to not "snap" back to place along the previous up vector when a user swipes, and for the life of me, I cannot get it to cooperate.
Currently, what I'm doing to update the up vector (based off of another stackoverflow thread with a similar issue) is this:
//Current full 360 degree angle of rotation, calculated earlier
let radian = THREE.Math.degToRad(full);
//Create new vector at radian angle to camera's current position
let v1 = new THREE.Vector3(_this.object.position.x + Math.cos(radian), _this.object.position.y + Math.sin(radian), _this.object.position.z).sub( _this.object.position ).normalize();
//_this.target = 0,0,0
let v2 = _this.target.clone().sub( _this.object.position ).normalize();
//Cross vectors to get the proper up
let v3 = new THREE.Vector3().crossVectors( v1, v2 ).normalize();
_this.object.up.copy( v3 );
And this works... up to the point where the camera seemingly inverts once I head near the side of the globe opposite the camera's starting position (0,0,1.75) and then negates my rotations (as far as I can tell) which causes the same "snap" to a different rotation like before.
Once I rotate the camera, I want it to maintain the rotation when using lookAt, regardless of the lookAt inverting everything.

ThreeJS object quaternion rotation not following axis

I am trying to get a 3D object to follow a 3D path so that it always faces the direction in which it is traveling. I try to do this by doing:
fishObject.quaternion.setFromAxisAngle(axis, radians)
where radians is the angle between an up vector and the direction of travel
In the following pen, the axes are depicted for clarity. The blue line is the axis, the purple one is just up, and the moving red line is the direction the fish should be facing (tangent). They all move in the right way, but when I set the quaternion, the rotation of the object does not seem to follow its axis
There is a bit of clutter in the pen (to build the fish), but all I am looking at is line 281 and its arguments:
fishObject.quaternion.setFromAxisAngle(axis, radians)
I am just new to this. Should be simple to someone familiar with 3D rotation.
https://codepen.io/nth-chile/pen/ELQqqb
Thanks, and please let me know if I can be more clear.
One way to get a tangent frame that is well-behaved is use the lookAt() method.
var axes = new THREE.AxesHelper( 10 );
scene.add( axes );
. . .
// then, in the render loop
pt = swimPath.spline.getPoint( t );
tangent = swimPath.spline.getTangent( t );
axes.position.copy( pt );
axes.lookAt( pt.add( tangent ) );
Now, make sure your "fish" is oriented so it faces the local positive-z axis by default. It is not, in your case, so you will have to apply a rotation. Add the object as a child of the tangent frame.
fishObject.rotation.set( 0, - Math.PI / 2, 0 );
axes.add( fishObject );
three.js r.92

Graphing 2d plane in 3d space using equation and/or vectors

I'm trying to make a linear regression plane visualization tool for a math project. Currently I have the math parts completed, but I am not sure how to graph the plane. I have a equation in the form of z=C+xD+yE, where C, D, and E are known constants. How do I graph the plane using these information? Thanks.
github page: https://saxocellphone.github.io/LAProject/
z=C+xD+yE
This equation gives full information about the plane. What else you need to graph (plot, draw?) it? Probably it depends on your graphic software possibilities.
Canonical form of given equation:
xD + yE - z + C = 0
Normal to the plane is (D, E, -1). Distance to the coordinate origin Abs(C)/Sqrt(D^2+E^2+1).
Plane intersects coordinate axes at values (-C/D), (-C/E), (C)
I see your problem is not with math, but with three,
as WestLangley pointed out in his comment you can play with rotations etc. or create a simple triangle which is the easiest way
since you have your equation for the plane create 3 points to form a triangle
// z=C+xD+yE
// i assume here that the plane is not aligned with any axis
// and does not pass through the origin, otherwise choose the points in another way
var point1 = new THREE.Vector3(-C/D,0,0);//x axis intersection
var point2 = new THREE.Vector3(0,-C/E,0);//y axis intersection
var point3 = new THREE.Vector3(0,0,C);//z axis intersection
now form a new geometry as in How to make a custom triangle in three.js
var geom = new THREE.Geometry();
geom.vertices.push(point1);// adding vertices to geometry
geom.vertices.push(point2);
geom.vertices.push(point3);
// telling geometry that vertices 0,1,2 form a face = triangle
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
create a simple material and add it to a scene
var material = new THREE.MeshBasicMaterial({
color: 0xff0000, // RGB hex color for material
side: THREE.DoubleSide // do not hide object when viewing from back
});
scene.add(new THREE.Mesh(geometry,material));
that should get you going, you can add another triangles, or make it larger with choosing points that are further apart

Three.js - rotating an Object3D around an axis

I'm trying to rotate a mesh loaded into an Object3D using OBJMTLLoader.
var obj = new THREE.Object3D();
// loading and stuff
obj.rotation.y += 0.1; //inside the update function
This works as it should, but only for y and z axes. Using the same code, but for the x axis yields the same result as rotating it around the z axis, but clockwise instead of counterclockwise.
Unfortunately, I need to rotate it around the x axis.
var xAxis = new THREE.Vector3(1,0,0);
obj.rotateOnAxis( xAxis, 0.1 );
This does rotate the object around the x axis.
However, I want to tween the rotation of the object, so I need a way to explicitly change the angle an object is rotated by, instead of rotating it for a specific amount.
Any ideas why obj.rotation.y and obj.rotation.z work properly, but obj.rotation.x doesn't?
Upon loading the mesh (before trying to rotate it around the x axis), I rotated it by 90 degrees around the y axis. Because of the default Euler order (which is XYZ), the local axes no longer corresponded to the world axes.
obj.eulerOrder = 'YXZ';
Using the above line of code before rotating the mesh around the y axis solved the problem.
A pretty good explanation of Euler order can be found here.

Three.js - Rotating a sphere around a certain axis

I have a problem. In Three.js, I want to rotate a sphere (Earth) around axis tilted by 23.5 degs. I found sphere.rotation.x, sphere.rotation.y and sphere.rotation.z, but when I combine them in the correct ratio, the sphere's rotation is quite weird - it has no permanent rotation axis. I think I need a function like sphere.rotation.vector(1,0,-1). Does anyone know how this function is called and how the correct syntax is?
Many thanks for answers!
You do not have to understand how Euler angles or quaternions work to do what you want. You can use
Object3D.rotateOnAxis( axis, angle );
Object3D.rotateOnWorldAxis( axis, angle );
Make sure axis is a unit vector (has length 1), and angle is in radians.
Object3D.rotateOnAxis( axis, angle ) rotates on an axis in object space.
Object3D.rotateOnWorldAxis( axis, angle ) rotates on an axis in world space.
three.js r.104
You need to use quaternions for this. This video explains what quaternions are and how they are used in 3D graphics.
You can construct a quaternion like this:
quaternion = new THREE.Quaternion().setFromAxisAngle( axisOfRotation, angleOfRotation );
Then you apply it to your object by:
object.rotation.set( new THREE.Euler().setFromQuaternion( quaternion ) );
You can also achieve this by using object hierarchies. For example, you can make an Object3D() instance and tilt it by 23.5 degs, then create a sphere (Earth) and add it to the tilted object. The sphere will then rotate around the tilted Y axis. Quaternions however, are the best tool for solving this.
var quaternion = new THREE.Quaternion();
var object = scene.getObjectByName('xxx');
function render(){
quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0).normalize(), 0.005);
object.position.applyQuaternion(quaternion);
}
three.js version is 86, see full example on codepen.
You can rotate your sphere using th 'ObjectControls' module for ThreeJS that allows you to rotate a single OBJECT (or a Group), and not the SCENE.
Include the libary:
then
var controls = new THREE.ObjectControls(camera, renderer.domElement, yourMesh);
You can find here a live demo here: https://albertopiras.github.io/threeJS-object-controls/
Here is the repo: https://github.com/albertopiras/threeJS-object-controls.
Hope this helps

Categories