Rotate around World Axis - three.js

I tried to rotate an object arount the Worlds-Y-Axis, with
myObject.rotateOnWorldAxis(new THREE.Vector3(0,1,0),THREE.Math.degToRad(1));
but the result was, that the object is only rotated in object space.
To be sure that I used the correct method I looked into the documentation and found that there are three methods to rotate an object:
.RotateY(rad) // rotate in Local Space
.rotateOnAxis(axis,rad) // rotation in Object Space
.rotateOnWorldAxis(axis,rad) // rotation in World Space
It seems that I used the correct method.
Is this a bug or an understanding problem on my side?
Here is a JSFiddle which illustrates my problem (the blue cube should rotate around the world axis).
Here is a second Fiddle where thy cyan cube is a child of another object.

It looks to me like your real question isn't regarding world space or object space rotations, cause those are working as expected in your examples.
You probably meant, how to change the point of rotation of an object. If that is the case, you have two options, you can either translate all your geometry vertices in respect to a pivot point of rotation. That way, your pivot will be centered at (0,0,0) and your vertices will rotate in respect to that.
mesh.geometry.translate( x, y, z );
Or you can make your object a child of a different Object3D (pivot), position your original mesh similarly to what was described above and rotate your pivot mesh.
var cube = new THREE.Mesh( geometry, material );
var pivot = new THREE.Object3D();
cube.position.set( 0, 12, 30 ); // offset from center
pivot.add( cube );
scene.add( pivot );
//...
pivot.rotation.y += Math.PI/2;
JSFiddle

Related

Three.js - get terrain height (position.y) of the mesh at specific position.x,z - without mouse and raycaster?

Let's say I have a sort of rather simple terrain from Blender exported as GLB object, which is a Group and contains a Mesh with BufferGeometry. I have another GLB object which is a model of vehicle. How can I read proper position.y at specific x,z locations (idealy 4 locations for setting car position and rotation) without moving mouse and using raycaster? I need to know what is elevation and height at specific region. Any simple clue without game-physics engine on top of ThreeJS?
Just use a Raycaster. I don't know why you don't want to use it, it's the easiest way to find an intersection without a physics engine and without tons of math.
Simply use Raycaster.set() to point straight down from your XZ coords and see where it intersects the terrain:
var ray = new THREE.Raycaster();
var rayPos = new THREE.Vector3();
// Use y = 100 to ensure ray starts above terran
rayPos.set(x, 100, z);
var rayDir = new THREE.Vector3(0, -1, 0); // Ray points down
// Set ray from pos, pointing down
ray.set(rayPos, rayDir);
// Check where it intersects terrain Mesh
let intersect = ray.intersectObject(terrainMesh);
console.log(intersect);
See here for the intersect object. It includes the point in space where the intersection takes place.

Rotating an Object properly around a pivot point given axis and angle

In Three.js there seems to be quite a few ways of rotation which i personally do not find very intuitive. See e.g. the example
http://cloud.engineering-bear.com/apps/robot/robot.html
I get very strange unexpected effects when I apply rotation to multiple objects. E.g. when I rotate objects that have been added to each other and start rotating the parent the individual objects will all over sudden by placed differently in respect to each other then they originally where. I am now experimenting with grouping and would like to avoid the same effect.
See http://pi-q-robot.bitplan.com/example/robot?robot=/models/thing3088064.json for the current state of affairs and https://github.com/BITPlan/PI-Q-Robot for the source code.
So i searched for proper examples following the different API options:
rotation
function renderScene() {
stats.update();
//side1.rotation.z += 0.02;
pivot.rotation.z += 0.02;
https://jsfiddle.net/of1vfhzz/1/
https://github.com/mrdoob/three.js/issues/1958
rotateOnAxis
three.js rotate Object3d around Y axis at it center
How to rotate a 3D object on axis three.js?
ThreeJS - rotation around object's own axis
rotateAroundWorldAxis
object.rotateAroundWorldAxis(p, ax, r * Math.PI * 2 / frames);
How to rotate a object on axis world three.js?
https://stackoverflow.com/a/32038265/1497139
https://jsfiddle.net/b4wqxkjn/7/
THREE.js Update rotation property of object after rotateOnWorldAxis
rotateOnWorldAxis
object.rotateOnWorldAxis( axis, angle );
Rotate around World Axis
rotateAboutPoint
Three JS Pivot point
Rotation anchor point in Three.js
setRotationFromAxisAngle
https://threejs.org/docs/#api/en/core/Object3D.setRotationFromAxisAngle
setEulerFromQuaternion
quaternion = new THREE.Quaternion().setFromAxisAngle( axisOfRotation, angleOfRotation );
object.rotation.setEulerFromQuaternion( quaternion );
Three.js - Rotating a sphere around a certain axis
applyMatrix
this.mesh.updateMatrixWorld(); // important !
childPart.mesh.applyMatrix(new THREE.Matrix4().getInverse(this.mesh.matrixWorld))
Applying a matrix in Three.js does not what I expect
I like the jsFiddle for https://stackoverflow.com/a/56427636/1497139
var pivot = new THREE.Object3D();
pivot.add( cube );
scene.add( pivot );
I also found the following discussions
pivot issue in discourcee.three.js.org
https://discourse.threejs.org/t/rotate-group-around-pivot/3656
https://discourse.threejs.org/t/how-to-rotate-an-object-around-a-pivot-point/6838
https://discourse.threejs.org/t/set-dynamically-generated-groups-pivot-position-to-the-center-of-its-children-objects-position/6349
https://discourse.threejs.org/t/my-3d-model-is-not-rotating-around-its-origin/3339/3
https://jsfiddle.net/blackstrings/c0o3Lm45/
https://discourse.threejs.org/t/rotate-object-at-end-point/2190
https://jsfiddle.net/f2Lommf5/3594/
Questions
None of the above information is clear enough to get to the point of the problem to be solved. The graphics above are much clearer stating the problem than the proposals are stating a solution.
a)
I'd like to use the cylinder as the axis even when the cylinder is moved.I'd expect the easiest way to go would be to use rotateAroundWorldAxis - is that available in the latest revision from three.js or do i have to add it from e.g. https://stackoverflow.com/a/32038265/1497139?
b) I'd like to get a chain of objects to be rotated to later apply inverse kinematics as in
https://github.com/jsantell/THREE.IK
https://jsantell.github.io/THREE.IK/
Although i looked at the source code of that solutions I can't really find the place where the parent-child positioning and rotating is happening. What are the relevant lines of code / API functions that would make proper rotation around a chain of joints happen?
I already looked in the Bone/Skeleton API of Three.js but had the same problem there - lots of lines of code but no clear point where the rotation/positioning between child and parent happens.
Question a)
Basically it works as expected:
cylinder.position.set( options.x, 15, options.z );
pivot.position.x=options.x;
pivot.position.z=options.z;
see
https://jsfiddle.net/wf_bitplan_com/4f6ebs90/13/
Question b)
see
https://codepen.io/seppl2019/pen/zgJVKM
The key is to set the positions correctly. Instead of the proposal at https://stackoverflow.com/a/43837053/1497139 the size is computed in this case.
// create the pivot to rotate around/about
this.pivot = new THREE.Group();
this.pivot.add(this.mesh);
// shift the pivot position to fit my size + the size of the joint
this.pivot.position.set(
x,
y + this.size.y / 2 + this.pivotr,
z + this.size.z / 2
);
// reposition the mesh accordingly
this.mesh.position.set(0, this.size.y / 2, 0);

How can I rotate around the center of an object in three.js?

I am dynamically adding a number of different objects of various sizes into a scene (one per click) and scaling and positioning them. Now I want to be able to rotate the objects around the Y axis at their center. I have added a boundingBox and an axesHelper, but the latter is showing up in the bottom corner of the objects. Reading this answer, which is similar to mine, it seems like this might be because of an offset. I can find the center of the object fine with this:
var box3 = new THREE.Box3();
var boundingBox = new THREE.BoxHelper( mesh, 0xffff00 );
scene.add( boundingBox );
box3.setFromObject( boundingBox );
center = box3.getCenter( boundingBox.position );
console.log( "center: ", center );
But when I try to reset the center to this position, following this answer, my object shoots way off into space.
box3.center(mesh.position);
mesh.position.multiplyScalar( -1 );
And I’m not really clear (even after reading the documentation) what “multiplyScalar” does/means. By playing with that number, I can get the object closer to the desired position, but the object still doesn't rotate around its center, and the AxesHelper is still at the original location.
Your object is not rotating around its center. Likely, your object's geometry is offset from the origin.
If you are dealing with a single Mesh or Line, you can center the object's geometry by calling
geometry.center();
This method will translate the vertices of the geometry so the geometry's bounding box is centered at the origin.
three.js r.97

Three.js - change camera POV on click

Some project background:
I have a Sprite particle field that is randomly generated. The camera is located at position 0, 0, 0. The particle field is all around the camera. I'm using Raycaster to be able to select the particle that is clicked on and change it's color. Once clicked I would like the camera to focus on this particle. I'm also attempting to use Tween to glide the particle into view.
I've attempted several different methods and none of them work. They are described here:
A traditional lookAt method that used Raycaster to pick up the intersect point from clicking.
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, this.camera);
var intersects = raycaster.intersectObjects( this.starfield.children );
this.camera.lookAt(intersects[0].object.position)
A distanceTo method where the distance between the camera and the intersect coordinates is used to move the camera. This only moves the camera along the z plane. It wont actually change its POV.
var cameraPosition = new THREE.Vector3(this.camera.position.x, this.camera.position.y, this.camera.position.z);
var intersectPosition = new THREE.Vector3(intersects[0].object.position.x, intersects[0].object.position.y , intersects[0].object.position.z );
var zoomPos = intersectPosition.distanceTo( cameraPosition );
const newCameraPosition = cameraPosition.addVectors(this.camera.position, vector.setLength(zoomPos));
I calculated the angle of rotation for each X, Y, and Z axis via tan and cos equations. I then attempted to rotate the camera by those degrees. I even tried converting them to radians to see if that would make a difference with the rotation method. It didnt :(
I don't know what else to do. At this stage I'm completely open to a different approach as long as I get this camera working. I'm very stuck,
any help would be greatly appreciated!
Instead of using
intersects[0].object.position
try using
intersects[0].point
.point is the world space position of the hit.
.objectis the object the triangle belongs to. .object.position is just the origin of that object, in this case the particle system. The particle positions themselves are relative to this origin.

THREE.js checking how close the camera is to a mesh

I have a mesh landscape in THREE.js that the camera points down at, I'd like to maintain a certain distance from that mesh (so if there's peaks in the terrain the camera moves further away).
I thought raycasting would be the correct way to start going about this (by getting the intersection distance) but all the examples I find relate to using mouse co-ordinates; when I try to set the origin as the camera position, and the direction co-ords to be the camera position but with a 0 on the Y axis (so camera up in the air facing down) the intersect results come up empty.
For example, on the render event I have:
t.o.ray.vector = new THREE.Vector3(t.o.camera.position.x, 0, t.o.camera.position.z );
t.o.ray.cast = new THREE.Raycaster(t.o.camera.position,t.o.ray.vector );
t.o.ray.intersect = t.o.ray.cast.intersectObject(object, true);
console.log(t.o.ray.intersect);
This results in an empty array, even when I'm moving the camera, the only way I can seem to get this to work is by using the examples that rely on mouse events.
Any ideas what I'm missing?
I realised it was because that setting 0 as the Y property was not enough. I had assumed that the vector co-ordinate simply helped calculate the direction in which the ray was pointing in, but this doesn't seem to be the case. i.e. -:
t.o.ray.vector = new THREE.Vector3(t.o.camera.position.x, -1000, t.o.camera.position.z );
t.o.ray.vector.normalize();
t.o.ray.cast = new THREE.Raycaster(t.o.camera.position,t.o.ray.vector );
t.o.ray.intersect = t.o.ray.cast.intersectObject(t.Terrain.terrain, true);
Produces the expected results.
What about this approach:
console.log( t.o.camera.position.distanceTo(t.o.vector.position) );

Resources