THREEJS Convert XYZ coordinate to Object rotation - javascript

I'm working with THREE JS. I have a sphere object (made using THREE.SphereGeometry) and inside this sphere I have another smaller sphere. Both spheres have the same center (so the smaller sphere sits exactly in the middle of the bigger sphere). My camera is located inside the bigger sphere and I can see the inside surface of the bigger sphere (Im inside a 3D shop). Here I create the bigger outer sphere:
setupSphereProjection() {
// creation of a big sphere geometry
//THREE.SphereGeometry(SPHERE RADIUS, WIDTH SEGMENTS, HEIGHT SEGMENTS)
this.sphere = new THREE.SphereGeometry(sphereRadius, 40, 40);
this.sphere.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1));
// creation of the sphere material
let sphereMaterial = new THREE.MeshBasicMaterial();
let loader = new THREE.TextureLoader();
loader.crossOrigin = "anonymous";
sphereMaterial.map = loader.load(testImage);
// geometry + material = mesh (actual object)
this.sphereMesh = new THREE.Mesh(this.sphere, sphereMaterial);
this.scene.add(this.sphereMesh);
}
My setup is such that when I click on the surface of the bigger sphere I get an XYZ coordinate of the click on the bigger sphere surface. What I want is for the smaller sphere to rotate to face the location of the XYZ coordinate. (so when the user clicks on the surface of the bigger sphere the smaller sphere rotates to look at the location of the click on the outer sphere). Here is the THREE.Vector3 I get when I click on the surface of the outer sphere (radius is 100):
THREEE.Vector3 {x: -8.755543860298761, y: -2.284054920077946, z: -99.22118491615181}
I'm struggling to convert the XYZ coordinate into a rotation of the inner sphere. I'm not sure if I should use Quaternions or Euler angles or both. I've tried different approaches and none of them have worked so far. Any help/advice would be warmly welcomed.

Related

Partial Equirectangular Panorama Three.js

I've got full equirectangular images working well with Three.js:
scene = new THREE.Scene();
geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
geometry.scale(-1, 1, 1);
material = new THREE.MeshBasicMaterial({ map: texture });
mesh = new THREE.Mesh(geometry, material);
mesh.rotation.y = Math.PI;
scene.add( mesh );
But my images actually only contain 180x180 degrees (half the sphere) so I'm trying to get a square texture partially applied on the spherical mesh without stretching the image across the entire sphere. I figure it has something to do with the texture.offset.xyz parameters, but I haven't been successful. While I can continue to pad my images to conform to 2x1 Equirectangular standards, I'd rather cut this step out of my processing workflow.
Below you'll find both the full equirectangular image and the square one I'm trying to get working. Does anyone have any clues on how to accomplish this? Thanks!
SphereBufferGeometry has more optional parameters:
SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
radius — sphere radius. Default is 50.
widthSegments — number of horizontal segments. Minimum value is 3, and the default is 8.
heightSegments — number of vertical segments. Minimum value is 2, and the default is 6.
phiStart — specify horizontal starting angle. Default is 0.
phiLength — specify horizontal sweep angle size. Default is Math.PI * 2.
thetaStart — specify vertical starting angle. Default is 0.
thetaLength — specify vertical sweep angle size. Default is Math.PI.
you can use phiStart, phiLength, thetaStart and thetaLength to define partial sphere
so to do an half sphere you can try something like:
geometry = new THREE.SphereBufferGeometry( 500, 60, 40, 0, Math.PI, 0, Math.PI );
reference http://threejs.org/docs/#Reference/Extras.Geometries/SphereBufferGeometry
The error is not in source code, it's in texture images: they are both wrong.
A 180 degrees fisheye like this:
reprojected into equirectangular will look like this:
Your textures looks like a mix of 360x180 equirectangular and 270° fisheye, wihich looks like this (with wrong labels/numbers, as I used same 180 FOV fisheye to create it):

Rotating Mesh in world axis - THREE.js

I'm having difficulty rotating an object. I am currently using THREE.Shape to configure a custom shape, after creating the shape, I configure it as a Mesh and set the position of it to:
buildingMesh.position.set( -70, -300, levelY );
Now because of the position of the mesh as well as the camera it appears as if its standing up.
Heres what that looks like:
Now I recently added a Orbital camera that rotates around the world axis, once the camera moves, this is how it looks:
Now this makes sense because the y axis was never configured when using the Three.Shape. What I am trying to figure out now is how can I turn that object so it appears to be standing up, as shown in the first image. I have tried using rotation on the x,y,z axis's but it always seems to only rotate within the objects axis.
Any suggestions?
Heres something I tried that I found on another question:
rotateAroundWorldAxis: function(object, axis, radians) {
this.rotWorldMatrix = new THREE.Matrix4();
this.rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
this.rotWorldMatrix.multiply(object.matrix); // pre-multiply
object.matrix = this.rotWorldMatrix;
object.rotation.setFromRotationMatrix(object.matrix);
}
Try:
mesh.rotate.x = Math.PI // will rotate over x axis 180 degree
where 'mesh' is object you have created (you can rotate 'y' and 'z' too)
So the primary problem here was that the mesh was built by multiple layers. All these layers actually had to be grouped together into an Object3D Which in turn allowed me to simply do: group.rotateOnAxis(axis,Math.pow(Math.PI, 2) / 2);
Hope this helps anyone in the future.

How to get 3D point coordinates given UV coordinates on a 3d plane object - Threejs

I'm trying to build some simple data visualisation and my weapon of choice is Three.js.I'have a series of PlaneGeometry meshes on which I apply a transparent texture dynamically created with a series of red square on it drawn at different opacity values.My plan is to use those points to create other meshes ( eg. CylinderGeometry ) and place them on top of the red square with an height value based on the red square opacity value.So far I could manage to find the UV values for each square and store it to an array, but I'm getting blocked at converting such red square UV coordinates to the 3D world coordinates system.I've found several resource describing the same concept applied to a sphere, and surprisingly it is pretty straight forward, but no other resources about applying the same concept to other mesh.
How can I get the 3D coordinates of those red square inside the texture?
EDIT: I think this is it:
function texturePosToPlaneWorld(planeOb, texcoord)
{
var pos = new THREE.Vector3();
pos.x = (texcoord.x - 0.5) * PLANESIZE;
pos.y = (texcoord.y - 0.5) * PLANESIZE;
pos.applyMatrix4(planeOb.matrix);
return pos;
}
Is used like this in the jsfiddle I made: http://jsfiddle.net/L0rdzbej/2/
var texcoord = new THREE.Vector2(0.8, 0.65);
var newpos = texturePosToPlaneWorld(planeOb, texcoord);
cubeOb.position.copy(newpos);
Planes are simple. The edge between vertices A, B -- vector A->B defines the direction for 'x' in your texture, and A->C similarily for the other direction in which the plane goes in the 3d space .. where you have texture's 'y' mapped on the plane.
Let's assume your pivot point is in the middle. So that's known in world space. Then as UV go from 0 to 1, e.g. UV coord (1.0, 0.5) would be in half way of the full width of the plane in the direction of the vector from of your Plane object pivot .. going from middle all the way to the edge. And then in the middle otherwise, where you have 0.5 in V (as in normalized texture y pixelcoord).
To know the coordinates of the vertices of the plane in world space, you just multiple them with the orientation of the object..
Given you know the size of your plane, you actually don't need to look at the vertices as the orientation of the plane is already in the object matrix. So you just need to adapt your UV coord to the pivot in middle (-0.5) and multiply with the plane size to get the point in plane space. Then the matrix multiplication converts that to world space.

Three.js - ExtrudeGeometry using depth and a direction vector

I want to extrude a shape and create an ExtrudeGeometry, but the shape has to be extruded into a certain direction. I have a direction in a Vector3
The shape is drawn in in the x, y plane and normally the z is the extrude direction (extrusion depth). So a direction vector (0,0,1) would result in the default extrusion. But for example a (0,0,-1) would extrude the shape in the other direction.
I first tried to use an extrude path to achieve this, but when using a path the shape is allowed to "spin" freely and the initial orientation is arbitrary. This is not what I need, the shape must stay oriented as is. You can read details on this here in my previous question.
I already came up with the idea of applying a matrix to the second half of the vertices of the resulting ExtrudedGeometry, but I cannot seem to get the geometry I want. Maybe it is my clumsy use of matrices, but I think that the face normals are pointing inside out after this trick.
Note The direction vector will never be orthogonal to the z axis since this would give invalid shapes
So the question:
How do I get a reliable solution to extrude my shape into the given direction. Here an example. The shape is a square in the x,y plane (width and length 2000) the extrusion depth is also 2000 and three different vectors with a drawing of the expected result seen in 2D (front view) and 3D.
Extrude your geometry in the usual way by specifying an extrusion depth, and then apply a shear matrix to your geometry.
Here is how to specify a shear matrix that will tilt a geometry.
var matrix = new THREE.Matrix4();
var dir = new THREE.Vector3( 0.25, 1, 0.25 ); // you set this. a unit-length vector is not required.
var Syx = dir.x / dir.y,
Syz = dir.z / dir.y;
matrix.set( 1, Syx, 0, 0,
0, 1, 0, 0,
0, Syz, 1, 0,
0, 0, 0, 1 );
geometry.applyMatrix4( matrix );
(The three.js coordinate system has the y-axis up -- unlike in your illustration. You will have to accommodate.)
three.js r.113

How to strech(scale) mesh on the world axis

There is an online 3d editor where you can edit individual meshes (move, scale, rotate). Ability to edit meshes implemented using custom transform controls which based on threejs's TransformControls code. This is fragment from mousemove event:
var intersect = intersectObjects(pointer, [xzPlane]); // intersect mouse's pointer with horizontal plane
var point = new THREE.Vector3();
point.copy(intersect.point);
point.sub(offset); // coords from mousedown event (from start stretching)
// some code for 'scale' value calculating base on 'point' variable
// var scale = ...;
//
mesh.scale.x = scale;
This code works well if the mesh does not rotate.
Requires scaling always happened to the world coordinate system. This is programming question
For example, from this:
To this:
P.S. I think that custom mesh matrix must be created, but I have very little experience with matrices
Thanks!
Instead of setting the rotation, like so:
mesh.rotation.set( Math.PI/4, 0, 0 );
apply the identical rotation to the geometry, instead:
var euler = new THREE.Euler( Math.PI / 4, 0, 0 );
mesh.geometry.applyMatrix( new THREE.Matrix4().makeRotationFromEuler( euler ) );
Now, you can set the scale and get the result you want.
mesh.scale.z = 2;
fiddle: http://jsfiddle.net/Tm7Ab/5/
three.js r.67

Categories

Resources